Reflection on Reflections from Damaged Life

Final Serenity

A newspaper obituary for a businessman once contained the words: “The breadth of his conscience vied with the kindness of his heart.” The blunder committed by the bereaved in the elevated language reserved for such purposes, the inadvertent admission that the kind-hearted deceased had lacked a conscience, expedites the funeral procession by the shortest route to the land of truth. If a man of of advanced years is praised for his exceptional serenity, his life can be assumed to comprise a succession of infamies. He has rid himself of the habit of getting excited. Breadth of conscience is passed off as magnanimity, all-forgiving because all-too-understanding. The quid pro quo between one’s own guilt and that of others, is resolved in favor of whoever has come off best. After so long a life one quite loses the capacity to distinguish who has done what harm to whom. In the abstract conception of universal wrong, all concrete responsibility vanishes. The blackguard presents himself as a victim of injustice: if only you knew, young man, what life is like. But those conspicuous midway through life by an exceptional kindness are usually drawing advances on such serenity. He who is not malign does not live serenely but with a peculiarly chaste hardness and intolerance. Lacking appropriate objects, his love can scarcely express itself except by hatred for the inappropriate, in which admittedly he comes to resemble what he hates. The bourgeois, however, is tolerant. His love of people as they are stems from his hatred of what they might be.

Yes.

Four-Hour Body Reviewed

Preamble

Tim Ferriss is a hustler and a cheat. These days, this is admirably referred to as marketing geniuuus. Why these behaviors become acceptable when they’re done at scale is debatable, but probably due to rampant consumerism, a poor understanding of capitalism, and the secretly held notion that if one must be tricked, let it be by an elaborate trick that plays on universally justifiable desires (money, family, safety, appearance). Because nobody wants to spend too long shamefully explaining why and how they were outwitted. OK, now we can talk about books.

Four (Big Muscles Remix)

I spent 15 minutes recreating Tim's favicon scaled up, then I spent 2 minutes ruining it with muscles.

The Book Review

As if you didn’t already know from The Internet, The Four-Hour Body (FHB) is the second book by Tim Ferriss, and is somewhat of a sequel to his fairly popular Four-Hour Workweek. Two different arenas, one equation: thinking outside the box yields unexpectedly reliable and portable success. One book is for time and money, the other for appearances and health. Here is the advertised list of problems FHB will fix:

  • How to prevent fat gain while bingeing (X-mas, holidays, weekends)
  • How to increase fat-loss 300% with a few bags of ice
  • How Tim gained 34 pounds of muscle in 28 days, without steroids, and in four hours of total gym time
  • How to sleep 2 hours per day and feel fully rested
  • How to produce 15-minute female orgasms
  • How to triple testosterone and double sperm count
  • How to go from running 5 kilometers to 50 kilometers in 12 weeks
  • How to reverse “permanent” injuries
  • How to add 150+ pounds to your lifts in 6 months
  • How to pay for a beach vacation with one hospital visit

I know it looks like it’s falling apart at the end and I’m making fun, but that’s the real list. And “that’s just the tip of the iceberg.”

Praise

  • FHB reads well (for me) – This is because it reads like — and, to some degree, is — a collection of blog posts. Clearly dressed up, but tastes the same. That’s not a bad thing, either; the book is supposed to be easily digestible. If it was any less straightforward, Tim couldn’t have written it.
  • Tim’s not half bad at supplements – Tim covers diet, exercise, and supplements. Of those three, if I had to pick a Jeopardy topic, I’d pick supplements. He’s name-dropped most of the currently accepted and speculatively exciting supplements.
  • In general, good fundamentals – The first few chapters cover some pretty respectable advice. Of course, I can say this because this isn’t the first place I’ve encountered it, but nevertheless, the diet and exercise basics are sound. Kettlebells, legumes, slowing down your eating, drinking more water, walking after meals, lots of stuff that you’ve probably heard here and there if you’ve ever made a conscious effort to get/stay healthy.

Criticism

  • Dude frequently takes it too far – Go back and read that summary list again. Now imagine each of those items is the endpoint of some reasonable bit of advice. It may be true, but it’s borderline dangerous to test. Plus there’s almost a hint of boasting/him daring you to try. It’s either that or a brief handwave that if you do all of the things in the book together, in the combination that works best for you, you’ll enjoy aforementioned effect.
  • Bad science – There’s a line in the beginning of the book where he says that he’ll teach you how to recognize the bad science and bad advice. Then the rest of the book is 10:1 anecdotes to academia. Granted, anecdotes are much less dry, if a bit predictable in favoring Tim’s practices, but they are not science and they definitely remind me of Jenny Craig.
  • Bay Area references – This is really minor, as the two points above really summarize my complaints about the content, but Tim mentions specific restaurants and specific locations in the Bay Area all throughout the book. Part of me thinks he or his editor wanted “stories” and so they needed to make the setting real. He mentions various alcohols by name, too. The book is probably better for it, but it seems very overt to me and makes me wonder how residents around the country will read it. Does it add mystique? Or does it alienate?

Conclusion

Well, I know that I will be trying out a few techniques. I’ve always been interested in maximizing health and minimizing work (hence the supplement research). Lately I’ve eased up on the last objective, so it’s a good time to try new things.

But is it a good book? Is it the health book for you? All in all, I would say that if you can ignore some of the insanity and focus on the message, it could be worth the $14, provided you are already pretty interested in this type of thing. That way, you have a bit of healthy skepticism and previous understanding in the area. It’s clearly written and organized and it incorporates a lot of modern knowledge in one spot. Still, I would not say it is a safe or engaging first step and it does not offer any replacement for discipline and motivation. I can definitely say that without those, this book is just as worthless as the others. If you think that you’d like the book, give me a shout and I can lend you my copy.

Ending, as we started, on the author: in my eyes, just as TV infomercial presenters gain a certain kind of celebrity, so has our Mr. Ferriss. The information presented in the book is indelibly his; it bears his all-too-direct marketing stamp, his signature form of enthusiastic and confident misinformation. While reading, try not to think about him too hard; you’ll probably just make yourself sad.

Gentoo Love: Intro to Portage Sets

A few quick gentoo tips before we get to the instructional material.

  1. Emerge world as often as you can. Once a week is probably a good frequency.
  2. Unless you’ve got a rock solid track record emerging world, don’t do it when you are really tired.
  3. In the best interest of the above, and your sanity, minimize the number of tilde keywords you have unmasked. I got all adventurous with one of my servers some years ago and there’s no good exit strategy. Sometimes it’s a pride point, other times, just pain.
  4. Don’t unmerge zlib. Just don’t, even if you are planning to put it right back. Pretty much nothing can run without it. Not portage, and not make, so you can’t get it back really. If you did, just copy libz.so (and symlinks) from another machine (probably of the same architecture).
  5. Also, don’t run eclean. It will break a lot of ebuilds and can’t even do that particularly well.

Getting setsy with portage

One of the main disadvantages of portage is the generally poor grouping of related packages. There are:

  • Package Categories (media-libs, dev-python, etc.) – These are pretty great, except when a package’s category changes and some ebuilds don’t pick up on that change. There is some way for portage people to redirect old ebuilds to new packages, but it has failed me more than once. Also, package categories don’t speak much to dependencies (not that they should). Portage/ebuild people decide on these, though the project maintainers might have some say.
  • Meta Packages (kde-meta) – Not many of these, but they seem to mostly be a dependency container. They are fine for installing, if a bit opaque, but they can be terrible for uninstalling. I’ve uninstalled old metas that left their obsolete and orphaned packages strewn about (kde 4.2 stuff). These are made by the project maintainers, I think.
  • “Profiles”(world, system) – Not a great name (maybe the wrong name?), but these aren’t as helpful and commonly used as they should be. Emerging world is definitely useful, but there could be a more granular operation between individual packages and ALL PACKAGES. These are generally automatically constructed for the user, though the user can do some manual editing.
Portage Screenshot

Oh KDE, you slay me.

Enter sets

Sets are basically like profiles, but the user gets a lot more control. They are groups of packages that can be reference like:

emerge --ask --update @my-set

You’ve got to admit that’s nicer than doing something like this.

Now when I said “Enter sets,” I meant… almost. Sets are only available in portage 2.2+. So the first step is to get that. Before that, I want to mention that it is technically still in alpha and a broken portage can make it hard to revert to a working portage. Nevertheless, so far it works fine for me and a lot of others have been using it since early 2009. In /etc/portage/package.unmask, add:

>=sys-apps/portage-2.2.0_alpha8

And in /etc/portage/package.keywords add:

sys-apps/portage ~*

Now, just emerge --ask portage and make sure it’s gonna pull in 2.2.

Your first set

Long story short, the format of the most basic user sets is just like the world file under /var/lib/portage/world. Just make a file with a list of packages, one per line, and put that file under /etc/portage/sets. For example, a set of scripting languages:


dev-lang/nodejs
dev-lang/php
=dev-lang/python-3.1.3
>=dev-lang/ruby-1.8.7_p249-r2
dev-lang/tcl

Now you can refer to that list of package like:

emerge --ask --update --deep @my-scripting-set

It may be prudent to prefix your sets so they don’t conflict with any other packages.

How to really clean up your system

By now you’ve probably seen the light, but I’m going to share one of my favorite uses so far to drive the point home. Say you’ve let your system go for a while, and you’ve accumulated some packages. Maybe you’ve switched from Gnome to KDE or maybe all the way to xmonad; regardless there is cruft to be removed. Here’s how you clean that stuff the Right Way:

  1. Update your gentoolkit and portage
  2. equery for some packages to remove and save the list:

    equery list kde-*/* > ~/kde_installed_packages_12122010

  3. Review the result and format properly. equery gives specific versions by defaults, so we’re just gonna throw ‘=’ in front of every line to make them valid package atoms. We’ll use sed:

    sed ':a;N;$!ba;s/\n/\n=/g' ~/my-kde-set

    You’ll have to manually add one more equal sign for the first line, but that should work.

  4. Review the result and move the file into place:

    mv ~/my-kde-set /etc/portage/sets/

  5. Depclean and unmerge:

    emerge --depclean --ask --verbose @my-kde-set

Ah, so fresh and so clean. You should move the set file out of the /etc/portage/sets directory now.

Conclusion

Sets fill a much-lamented (by me) gap in portage. They add organizational power without removing fine-grained control, without which Gentoo would not be Gentoo. My only concern is
Why did this take so long? Given that this is basically how ‘world’ has always worked and we’re well into version 2, we should have had this ages ago. Also, sets are really not that complex or tailored to package management, I wonder if archlinux or some other distro has solved this better. Of course, I’ve only scratched the surface, and there’s a lot more you can do with sets, it seems. For a good starting point, you can do a search on sets.conf.


P.S. The screenshot above was brought to you by ImageMagick:

import -window root ~/screenshot.png


JavaScript Patterns

Web applications these days, am I right? With all their user experience and fancy A/B tests. It’s all thanks to JavaScript, or, more correctly, browsers and developers alike finally biting the bullet, putting a paper bag over the language’s proverbial head, and getting some good use out of it.

Analogies aside, JavaScript is not so great, but the experts have found ways to reclaim their software engineering integrity. Buried under metric tonnes of “Top 43 jQuery Plugins and Extensions for the Colorblind”, you might actually find such a beacon of knowledge. One of those beacons is a new book, JavaScript Patterns, by Stoyan Stefanov.

My copy is already getting dog ears.

A little bit of personal background, a couple years back I was starting to feel pretty comfortable with jQuery and even started writing my own extensions (not for the colorblind). I was also reading a new book, JavaScript: The Good Parts, by Douglas Crockford. Even though I strongly recommend it, JS: TGP raised more issues than it clarified. Sure, don’t use this and that part of JavaScript, but is that all there is, just a minefield of features, waiting to trip me up? Furthermore, many of those antipatterns he described really only became problematic in larger projects. Shouldn’t I be more concerned about confidently architecting and building those larger projects? I was unable to convince myself that JavaScript was a safe platform on which a very small team could build a stable product. (I even have an ActionScript 3 book from those days.)

Now, end of 2010, enter JavaScript Patterns. It aims to provide insight and best practices for teams who want to create a JavaScript product that won’t be hell to develop and maintain. And for the most part, it’s successful. Stoyan is an engineer at Yahoo, working on YUI, and just off the top of my head, he’s also written Object-Oriented JavaScript and a chapter in High-Performance JavaScript.

Pros

  1. Really does deliver on holistic, well-justified JavaScript programming techniques that embrace the language.
  2. Assumes the appropriate amount of JavaScript and CS knowledge, not too much, not too little.
  3. Focuses mainly on JavaScript, not too much on the specifics of external libraries like jQuery. Libraries these days are big and numerous; a dedicated book for those would probably be more helpful. This one is library-agnostic and might even stay applicable longer.
  4. Adequate treatment of server-side JavaScript. By which I mean, almost none. Similar to the library issue above, server-side JavaScript is still JavaScript. It’s also very volatile and most of the server-side-specific stuff is not unique to JavaScript.

Cons

  1. Could give a little more focus to external libraries. I know I just got done saying that it was a good thing that it didn’t, but face it, almost everyone uses some external library. I think there’s a lot of general advice that one could give to allow developers to extract more from their library of choice while loosening any coupling that may occur along the way.
  2. Lulls a bit in Chapter 6, Code Reuse.
  3. The quote on the back of the book is probably the weakest bit.

    “Stoyan has written the go-to guide for JavaScript developers working on large-scale web applications.”

    Don’t get me wrong, it’s definitely my go-to guide (outside of good old Google), but the quote is from Ryan Grove, YUI Engineer. No offense to Ryan, but if you write a sweet book the publisher should try to hook you up with a quote from someone a little more prestigious than your own coworker.

And that’s all I have to say about that. For the time being, 8.5/10, highly recommended. It’s not very long and it really sets some precedents on which to build. For more study, I recommend you check out YUI Theater and follow some blogs. Ajaxian is great and all, but the real in-depth stuff comes out of projects and project contributors, check out Kangax’s blog (of Prototype fame) and Tim Caswell’s How to Node.

Facebook’s data export is broken

(Edit: It looks to me like Facebook’s engineers found this post and fixed the issue, though I’m not entirely sure as to the causation. You gotta give it to them, that’s some pretty responsive engineering.)

Jeez, guys, I only update once a month, why am I spending time on stuff like this? Because it’s easy to think about and I had a minute.

So you can export your data from Facebook now. Good on ya, Facebook. I even recovered my password to check out this killer feature. (Not this one.) Go to Account -> Account Settings -> Download Your Information.

Facebook will email you when a link to your zip is ready. I got my link in about an hour. My profile is kind of photo heavy and weighed in at 61MB.

You actually get a nice, lightweight, navigable profile. (See the above screenshot, shoutoutz to BBone, et. al.) Nothing’s paginated, so scroll away. It’s barely styled and I found myself wishing the normal Facebook UI was more like this. You’ve got almost everything here: your wall posts, your friend list, and your photos.

Wait, the last one. Something about the last one. Yeah, it doesn’t work. Looking at the code, it seems they’ve url-encoded the slashes in the img src and href, so stuff doesn’t show up. A few of the links do work, but they link to Facebook itself, which also seems broken, maybe. Code:

<a href="album-Profile%20Pictures.html"><img width="149" height="200" src="../photos%2FProfile%20Pictures%2F432293561980.jpg"/></a>
<br/>

I was this close to being done, but now I’ll have to wait for this bug to get fixed to redownload. In the meantime, you may comment on this post and pretend it’s my Facebook wall because I’m going to go randomize my password again.

Scripts for Gibsons: TimePropagate

This boat's in front of that boat and my boat's the last boat.

As the privileged few users of my FTP server can attest, I like to keep it tidy. Of course, in administrating a 5TB fileserver, scripts emerge to help keep things organized. Below is one such script that a least a couple of you readers could use. I made it and it’s no masterpiece, but it is LGPL, so this is my first potentially actually useful foray into open-source. What was originally an 8-line bash script has grown into a couple hundred of PHP (don’t you dare judge me) for readability and maintainability.

Read the comment at the top of the code to understand what timepropagate actually does. Usage is also in the script.

Sample output

As run on my ftp (with extra stats enabled)

Processed 69780 files (9 links) and 5439 directories, 2 out of date (0 touchable).
Maximum directory depth seen was 8.
The newest modified date seen was September 12, 2010, 8:55 pm.
Extension counts:
        mp3 - 45882
        avi - 6872
        wav - 3636
        jpg - 3521
        m4a - 2373
        aif - 1054
        mkv - 646
        mp4 - 428
        txt - 309
        bmp - 270
        flac - 264
        zip - 239
        mpg - 230
        gif - 224
        exe - 220
        amd - 185
        ogm - 185
        pdf - 180
        slp - 126
        srt - 124

Code

Download TimePropagate here.

#!/usr/bin/php
<?php

/*
 * TimePropagate 
 * An uncreatively-named script to breathe life into directory modified times
 *
 * As users of my ftp server might know, most linux filesystems that I know of 
 * don't propagate the modified-by date of directories. So, if I have a folder
 * called 30 Rock, with subdirectories for each season, adding a new episode
 * to "Season 5" isn't going to produce the desired results when viewing the
 * full listing of TV Series sorted by modified times.
 * 
 * Long story short, sorting by modified date is more useful when you run this
 * command, usually. If you can come up with some scenarios where the default
 * behavior is actually useful (and not just a performance bonus), let me know.
 *
 * In the meantime, run it with the -pv flags in the directory of your choice
 * to see how it works for you.
 *
 * All this is licensed LGPL.
 */

 // for easily-glanced-at log lines
 define('GLANCE_OK', 'OK');
 define('GLANCE_NOTE', '**');
 define('GLANCE_ERROR', '!!');
 define('GLANCE_TITLE_WIDTH', '19');
 
$options = parse_arguments($argv);
$mdc = new ModifiedDateController($options);

if($mdc->help) { // if user asks for help/usage
	print_usage($argv[0]);
	exit();
}

$continue = true;
if(!$mdc->force) { // if not force
	$continue = ask($mdc->target_dir);
}

if(!$continue) {
	echo "You and me are done.\n";
} else {
	$mdc->process();
}


function print_usage($command) {
	echo "\nModified Time Propagate v1 - GPL 2010 Mahmoud Hashemi\n\n";
	echo "Usage: ", $command, " [-h] [-vpsfLN] [-m ] [-d ]\n\n";
	
	echo " -h \t- Print this message and exit.\n";
	echo " -v \t- Enable verbose output.\n";
	echo " -p \t- Pretend (does not write any dates; use this with verbose).\n";
	echo " -s \t- Gather and show some miscellaneous statistics.\n";
	echo " -f \t- Suppress confirmation.\n";
	echo " -L \t- Follow links (careful, linked directories can greatly affect results).\n";
	echo " -N \t- Suppress recursion; only do the current directory.\n";
	echo " -m #\t- Max depth to recurse (default: 30).\n";
	echo " -d dir\t- Target directory (default: current directory).\n";
}

function ask($target_dir) {
	$stdin = $fh = fopen('php://stdin', 'r');

	echo 'Propagating file modification times for ', $target_dir,"\n";
	echo "Continue? (y/n)  ";

	$response = '';
	while(trim($response) === '') {
		$response = trim(strtolower(fgets($stdin, 8)));
	}
	if($response === null || ($response != 'y' && $response != 'yes')) {
		return false;
	} else {
		return true;
	}
}

class ModifiedDateController {
	public $current_uid = '';
	
	public $help = false;
	public $target_dir = '';
	public $follow = false;
	public $no_recurse = false;
	public $verbose = false;
	public $more_stats = false;
	public $pretend = false;
	public $force = false;
	public $max_depth = 30;
	
	public $files_seen = 0;
	public $links_seen = 0;
	public $folders_seen = 0;
	public $touchable_folders_seen = 0;
	public $max_depth_seen = 0;
	public $folders_updated = 0;
	public $extensions = array();
	
	function __construct($options=null) {
		if($options !== null) {
			if($options['h']) {
				$this->help = true;
			}
			if($options['L']) {
				$this->follow = true;
			}
			if($options['v']) {
				$this->verbose = true;
			}
			if($options['p']) {
				$this->pretend = true;
			}
			if($options['f']) {
				$this->force = true;
			}
			if(isset($options['D']) && $options['D'] !== '') {
				$this->max_depth = intval($options['D']);
				
				if($this->max_depth no_recurse = true;
				$this->max_depth = 0;
			}
			if($options['s']) {
				$this->more_stats = true;
			}
			if(isset($options['d']) && $options['d'] !== '') {
				$this->target_dir = $options['d'];
				
				if(!is_dir($this->target_dir)) {
					echo "Specify a valid target directory (-d).\n";
					exit(2);
				}
			} else {
				$this->target_dir = getcwd();
			}
		}
	}
	
	function process() {
		$this->current_uid = getmyuid();
		$newest_mtime = $this->r_filemtime($this->target_dir);
		echo "\n";
		echo "Processed ",$this->files_seen," files (", $this->links_seen," links";
		if($this->misc_files_seen > 0) {
			echo ", ",$this->misc_files_seen, " miscellaneous";
		}
		echo ") ";
		echo "and ",$this->folders_seen," directories, ",$this->folders_updated," out of date (";
		echo $this->touchable_folders_seen, " touchable).\n";
		echo "Maximum directory depth seen was ", $this->max_depth_seen,".\n";
		echo "The newest modified date seen was ",date("F j, Y, g:i a", $newest_mtime),".\n";
		if($this->more_stats) {
			arsort($this->extensions);
			echo "Extension counts:\n";
			foreach($this->extensions as $ext=>$count) {
				echo "\t",$ext," - ",$count,"\n";
			}
		}
	}
	
	// call this on a directory path.
	function r_filemtime($path, $depth=0) {
		if($depth > $this->max_depth) {
			if($this->verbose) {
				echo get_glanceline("Depth limit (".$this->max_depth.")",GLANCE_NOTE,$path);
			}
			return FALSE;
		}
		if(!file_exists($path)) {
			echo get_glanceline('No such path', GLANCE_ERROR, $path);
			return FALSE;
		}
		
		$path_mtime = filemtime($path);
		if($path_mtime === FALSE) {
			echo get_glanceline('Access denied', GLANCE_ERROR, $path);
			return FALSE;
		}
		++$this->folders_seen;
		if($depth > $this->max_depth_seen) {
			$this->max_depth_seen = $depth;
		}
		
		$max_mtime = 0;
		
		foreach(glob($path."/*") as $file) {
			$filetype = filetype($file);
			if($filetype === 'link') {
				++$this->links_seen;
				if($this->follow) {
					$link_target = realpath($file);
					if($link_target == FALSE) {
						echo get_glanceline("Dead link", GLANCE_ERROR, $link_target); 
						continue;
					} else {
						$file = $link_target;
						$filetype = filetype($link_target);
					}
				} else { //if we're not following links
					continue;
				}
			}
			
			if($filetype === 'dir') {
				$cur_mtime = $this->r_filemtime($file, $depth+1);
			} else if($filetype === 'file') {
				++$this->files_seen;
				if($this->more_stats) {
					 $ext = strtolower(end(explode('.',end(explode('/', $file)))));
					 if($ext === '' || strlen($ext) > 5) { //arbitrary 5 char ext limit
						continue;
					 } else if(isset($this->extensions[$ext])) {
						++$this->extensions[$ext];
					 } else {
						$this->extensions[$ext] = 1;
					 }
				}
				$cur_mtime = filemtime($file);
			} else {
				++$this->files_seen;
				++$this->misc_files_seen;
			}
			if ($cur_mtime > $max_mtime) {  
				$max_mtime = $cur_mtime;   
			}
		}
		if($max_mtime > $path_mtime) {
			$touchable = (fileowner($path) == $this->current_uid);
			if($touchable) { 
				++$this->touchable_folders_seen;
			}
			if(!$this->pretend) {
				if($touchable) {
					touch($path, $max_mtime);
				} else {
					echo get_glanceline("Can't touch this",GLANCE_ERROR,$path);
					++$this->touch_errors;
				}
			}
			++$this->folders_updated;
			if($this->verbose) {
				echo get_glanceline(date("M d, Y, H:i", $max_mtime),GLANCE_NOTE,$path);
			}
		} else {
			$max_mtime = $path_mtime;
			if($this->verbose) {
				echo get_glanceline(date("M d, Y, H:i", $max_mtime),GLANCE_OK,$path);
			}
		}
		
		return $max_mtime;
	}
}

function get_glanceline($title, $blip, $detail) {
	$title_width = GLANCE_TITLE_WIDTH;
	$title = str_pad($title, $title_width, ' ', STR_PAD_BOTH);
	return $title.' - [ '.$blip.' ] - '.$detail."\n";
}

function parse_arguments($argv) { 
    $arguments = array(); 
	array_shift($argv);
	$args = explode('-', implode(' ', $argv));
	foreach($args as $arg) {
		$arg = trim($arg);
		if($arg == '')
			continue;
		$arg_pair = explode(' ',$arg);
		if($arg_pair[1] == '') {
			$argarray = preg_split('//', $arg_pair[0], -1, PREG_SPLIT_NO_EMPTY);
			foreach($argarray as $char) {
				$arguments[$char] = true;
			}
		} else
			$arguments[trim($arg_pair[0])] = trim($arg_pair[1]);
	}
    return $arguments; 
} 

Some Words and Dedications

There you have it. Feel free to suggest features or make modifications or give me props. Also, thanks to Alan for offering some guidance/sane defaults pre-release, and Ben for getting me Chinese food as I was polishing this off.

Comedy

Friggin everyone loves to laugh. Even observatory domes.

Friggin everyone loves to laugh. Even observatory domes.

Dear readers, you all know I love to laugh. Almost as much as “hanging out with friends.” I’m fascinated by comedians; they occupy an extra special place in my heart of hearts. Let me share a thought I had about them.

Observation

There are virtually no good comedians under the age of 35.

I can’t find a single widely-known comedian whom I admire that is not 12 years older than I. I was in first grade, they were in their senior year of high school, if not already graduated. A sample (this also serves as an abridged list of my comedy heroes):

I could go on. Notice that even the “young” comedians — comedians whose primary audience tends to be young — are at the very least entering middle age.

Why?

What gives with the 19-year-old doctors, CEOs, and pop stars? The media love these wunderkind and dangle their success before us like we should have worked harder in school. But there is a difference. I think there is something intrinsic to comedy that is much more resistant to this kind of fluke. In no way, shape, or form can the media make a comedian. Enough plays on the radio will make any song with a beat catchy. But a joke just gets older and more stale. Something about humor demands perception and experience. Practice and study of the mechanics of the craft can only augment talent and exposure to life.

What really strikes me about these specialists who have been writing and thinking for years, is the material that actually makes it to our ears is relatively very limited. As if all those years attempting original, humorous thought netted only a few hours of stories worthy of public presentation. Presented and appreciated so casually! A joke, a laff. No wonder comedians are so humble; some part of them is aware of this brutal inefficiency.

And so I think it must go with any experience-driven occupation. Building on this post, youth does not favor the designer, the producer, the director.

Appendix

As with all claims, there are exceptions. Dave Chappelle had an early break with Half Baked. Tim and Eric are 34. Aziz Ansari is only 27 and he is a little past up-and-coming. Maybe it’s just a matter of getting discovered. Maybe it’s because the comedian stands alone, whereas the pop star is almost always backed by a team of producers and creative staff. Or maybe it’s because there’s just no rushing a good joke.