4/13/2008
I finally got around to using the
Digg API, which is superior to scraping the site. The change has prompted me to redesign the entire get/write process, which is a good thing. Also, I am starting to dig into the quirky JavaScript behavior in
WebKit. Since I am using Safari as my default browser, I feel compelled to get this working properly. Finally, expect a mobile version of Newspyle soon.
4/13/2008

About a year and a half ago, I worked on a project to
visualize del.icio.us tags. I created a layout engine and a neato graphics library in Python. A few weeks after the initial batch, I lost 90% of the code due to a hard disk failure.
While I have not bothered to recreate the code, I want to showcase a fun little experiment. I asked a bunch of notable bloggers/friends/peeps to give me a dump of their del.icio.us links/tags. I proceeded to visualize their tag intersections while keeping an emphasis on aesthetics. Even though it was a long time ago, I am very pleased with the results!
Go ahead and
view the project page for more awesomeness.
3/28/2008
It would be interesting if someone created a dependency management system like "apt" for JavaScript libraries.
3/09/2008
Up until taking his Series 7 examination, my younger brother was really nervous about failing. He asked me for preparation advice just two days shy of the exam. Rather than recanting study rituals or memorization tips, I confidently translated my core belief into English:
In a world without failure, there is only hard work and success.
This is something that has resonated with me for years. I am impressed that I was able to distill this idea into few words.
3/09/2008
So I caved in and picked up a new MacBook Pro. Having recently abandoned my iMac, this new laptop has become my primary workhorse. In the process of migrating data, I came across an old folder called "End of Babson Docs." Despite the descriptive label, I was curious as to what was stuffed in there...
It turns out that in my final hours of graduating college I copied/pasted everything on my desktop, bookmarks, fonts, various Photoshop Tennis files, random digital experiments, 2-3 web server root directories, and a bunch of of stray documents. The crazy thing about looking at this old data is that I actually remember the significance of most of the 1,500+ files.
The sad realization from all of this is that I may not be good with remembering names of acquaintances but I have no problem with recognizing old files and directory layouts. This is a new world.
1/12/2008
Here is a taste from an
excellent series of interviews conducted by Nintendo President Satoru Iwata:
I look at this as if I had borrowed a vegetable garden from Miyamoto-san. It was as if I had asked him, "Please let me borrow your secret garden. From it, I promise I will produce great things." Then I started sowing the seeds with my staff members, and after harvesting the crops and cooking the dish, we decided to have Miyamoto-san be the first one to taste it. He is the owner of the garden, after all. We sent every plate to Kyoto for him to sample, and he would comment back by saying things like, "this is a little too hot" or, "this tastes better". Towards the end of development, we had him come visit our "restaurant" in Tokyo. While he was here, we had him sample an unbelievable number of dishes. We had him eat until he was very full.
I am inspired to hunt down more game development interviews.
12/25/2007
I have spent the last few days cleaning out my Gmail with a little help from
Mihais' macros. I love spelunking through email using nothing but the keyboard - it takes me back to my Stanford days when I mucked around with Pine.
Despite the shortcuts, one thing has continuously irked me about Gmail - having to use the mouse to paginate. So, I hacked up Mihai's script to do pagination from the keyboard (using 1/2). Simply copy/paste the following blocks into 'actions':
// 1: older page for all mail
49: function() {
currentPage = GrabCurrentAllMailPage();
if (currentPage >= 2) {
window.location.hash = "#all/p" + (currentPage-1);
}
},
// 2: newer page for all mail
50: function() {
currentPage = GrabCurrentAllMailPage();
if (currentPage)
{
window.location.hash = "#all/p" + (currentPage+1);
}
else
{
window.location.hash = "#all/p2";
}
}
As you can see, both of those actions depend on the following helper function:
// Check the url for a pagination link - if you see /p# extract the #
// I should get a bit smarter and check the current page to do inbox routing
function GrabCurrentAllMailPage() {
var pageArray = window.location.hash.match(/^(.*)(\/)(p)([0-9]+)(.*)$/);
// If there is no hash, or the regex fails, then test for properties
if (pageArray)
{
if (pageArray.length != 6) {
return 1;
}
else {
return parseInt(pageArray[4]);
}
}
}
I had previously used -/+ for pagination, but the - key code is 0 - which was getting in the way of deleting, which is #. Oddly, that key code is also zero. Is it because of the shift key modifier?
Note, you must be on the all mail page for this to work properly. If you hit next page from the inbox, you will be routed to page 2 of all mail. Yeah, this is a bug and the code is totally ugly, but it's Christmas and I just want to read/clean my mail.
Happy holidays to all!
12/18/2007
In continuation of a
previous post of using predicates/lambdas in Python, I prepared some helpful list methods that you can drop into your current and future Python scripts. What follows in an introduction/walk-through of the five methods. Note, when I say predicate, I am referring to a literal value or a function pointer.
Exists(predicate)
* Returns true if the predicate is satisfied by at least one list member.
FirstIndex(predicate)
* Returns the first integer position in the list that satisfies the predicate.
FirstValue(predicate)
* Returns the first value in the list that satisfies the predicate.
* Note, the returned value may be a complex object.
LastIndex(predicate)
* Returns the last integer position in the list that satisfies the predicate.
LastValue(predicate)
* Returns the last value in the list that satisfies the predicate.
* Like FirstValue, the returned value may be complex.
Bored? Here is the overloaded list, which I am dubbing 'PredicateList':
from types import FunctionType
from UserList import UserList
class PredicateList(UserList):
def Exists(self, predicate):
"""Returns true if the predicate is satisfied by at least one list member."""
if type(predicate) is FunctionType:
for item in self.data:
if predicate(item):
return True
return False
else:
return predicate in self.data
def GetIndex(self, predicate, reversed):
"""Common functionality shared by FirstIndex and LastIndex."""
xr = xrange(len(self.data))
if reversed:
xr = xr.__reversed__()
for i in xr:
try:
if type(predicate) == FunctionType:
if predicate(self.data[i]):
return i
else:
if self.data[i] == predicate:
return i
# Function predicates that check object properties will fail on simple
# types like strings. This is rather unelegant, but works.
except AttributeError:
pass
return None
def FirstIndex(self, predicate):
"""Returns the first integer position in the list that satisfies the predicate."""
return self.GetIndex(predicate, False)
def FirstValue(self, predicate):
"""Returns the first value in the list that satisfies the predicate."""
firstObjectIndex = self.FirstIndex(predicate)
if not firstObjectIndex is None:
return self.data[firstObjectIndex]
else:
return None
def LastIndex(self, predicate):
"""Returns the last integer position in the list that satisfies the predicate."""
return self.GetIndex(predicate, True)
def LastValue(self, predicate):
"""Returns the last value in the list that satisfies the predicate."""
lastObjectIndex = self.LastIndex(predicate)
if not lastObjectIndex is None:
return self.data[lastObjectIndex]
else:
return None
Note, PredicateList extends UserList (this is found under your Python installation's lib/), which happens to be a Python wrapper for the list type. If you are curious, there is also a UserDict class that acts congruently for dictionaries. As you can see, everything above is straight-forward. I am however a bit embarrassed by catching the AttributeError exception; there is certainly a better way of accomplishing that - one way that comes to mind is to do a type check prior to grabbing the property value.
Alright, with that out of the way here is an example use-case. Suppose I had a Person class that looked like the following:
class Person():
def __init__(self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName
def __str__(self):
return '%s %s' % (self.firstName, self.lastName)
Now let's initialize a PredicateList and append some members. Note, I would have preferred to have simply used the [] notation, but this will have to suffice:
sampleList = PredicateList()
sampleList.append('3')
sampleList.append('2')
sampleList.append('1')
sampleList.append(Person('Joe', 'Shmoe'))
sampleList.append('5')
sampleList.append('2')
print sampleList
Now, we can use the PredicateList like so:
# Existence checks
print sampleList.Exists('2')
print sampleList.Exists(lambda x: x == '2')
# First index checks
print sampleList.FirstIndex('2')
print sampleList.FirstIndex(lambda x: x == '2')
# First object checks
print sampleList.FirstValue('2')
print sampleList.FirstValue(lambda person: person.firstName == 'Joe')
# Last index checks
print sampleList.LastIndex('2')
print sampleList.LastIndex(lambda x: x == '2')
# Last object checks
print sampleList.LastValue('2')
print sampleList.LastValue(lambda person: person.lastName == 'Shmoe')
There were things that I obviously omitted from this class. For instance, map() and filter() already take lambdas as function arguments, making operations like value casting and spawning new lists seem relatively simple.
There may be an oversight in the code above as this was a really fun 10 minute exercise with the REPL. I always appreciate feedback, so feel free to
drop me a line.
12/10/2007
I cannot express how much I love this clip - it's beautiful and has a great message. Whoever is heading the Zune marketing campaign at Microsoft seriously gets it. To me, this spot has much more personality than any iPod propaganda in the past few years. If you're curious, you can visit
Zune Arts.
12/04/2007
I have been spinning in Python for a few days now in an attempt to port some C# bits. In the C# codebase, I typically exercised the following:
List list = new List();
list.Add(PreviouslyInstantiatedType); // Imagine many populators
list.FindIndex(delegate(T) { T.someProperty == true; });
I love being able to pass in anonymous functions or function pointers around. Imagine building up a tree of nodes and returning the position in the tree where a given node's property has a specific value or a combination of values. Of course, the beauty of this relies on the underlying looping - boring stuff to constantly copy/paste throughout your code.
So as I was writing the equivalent Python, I came up with:
list = []
list.append(PreviouslyInstantiatedType)
list.index(lambda x: x.someProperty == True)
Everything looks cool - right? Well, that doesn't seem to work. It turns out that index does not seem to like functions/lambdas as evaluators.
Here is a first stab at implementing something for this. Note, I am just trying to cheaply clone C#'s list method "FindIndex" and have not checked out Python's list method "index."
def fIndex(f, list):
for i in xrange(len(list)):
if f(list[i]):
return i
return -1
This iterates through the provided list, and applies the function for every item. In this case, there should be some sort of type checking that the function is a boolean - rather than error catching.
In putting all of this together, imagine the following object and list:
class person:
def __init__(self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName
people = [person('j','h'),person('k','a'),person('n','g')]
If someone asked me to print out the first position in the list where the person's last name is 'a', I would do:
print fIndex(lambda p: p.lastName == 'a', people)
This whole thing is extremely simple - but I am loving it.