After I talk to someone I meet at a coffee shop or while traveling and help them with a small technical issue like getting photos transferred or getting on a wireless network, I’m sometimes asked for advice on becoming tech savvy. My advice for someone struggling with their PC who I won’t see again and won’t be able to help in the future is to get a mac. I point out that it really is totally different from a PC, and once they get a mac they should be able to figure out how to do a lot of stuff by themselves, instead of asking for help like they do now.

There is one thing, besides not wanting to pay extra money for a mac, that keeps people from empowering themselves by getting a windows-free computer that they can actually learn to use and maintain themselves — either they or someone they know has had hardware problems with a mac.

In my opinion, even if a mac breaks several times, it’s still worth it to get a mac (and an extended warranty) if you can’t figure out windows and need a computer for your career. I’m reminded of this by a comment by an editor on The Consumerist, an extremely popular and successful blog. He says that he’s had issues with three different macs and an iPod, but it’s still worth it to him to have a mac. Of course it is. He built a successful career with macs.

I just wrote my first GreaseMonkey user script. It’s a script that puts a random Benjamin Franklin quote above the stories on reddit to remind me to be dutiful and not spend too much time looking at online news. I found the quotes through (you guessed it) reddit.

Here’s what it looks like:

reddit_franklin.jpg

And here’s the code:

// ==UserScript==
// @name           Reddit Quotes
// @namespace      com.benatkin
// @description    Shows Quotes in front of Reddit
// @include        http://reddit.com/
// ==/UserScript==

function franklinQuote() {
  var quotes = [
    'Early to bed, and early to rise, makes a man healthy, wealthy and wise',
    'Diligence is the mother of good luck',
    'God helps them that help themselves',
    'Sloth, like rust, consumes faster than labor wears, while the used key is always bright',
    'Dost thou love life, then do not squander time, for that’s the stuff life is made of',
    'Lost time is never found again',
    'He that riseth late, must trot all day, and shall scarce overtake his business at night',
    'Drive thy business, let not that drive thee',
    'Industry need not wish',
    'He that lives upon hope will die fasting',
    'There are no gains, without pains',
    'Plough deep, while sluggards sleep, and you shall have corn to sell and to keep',
    'One today is worth two tomorrows',
    'Have you somewhat to do tomorrow, do it today',
    'Be ashamed to catch yourself idle',
    'Let not the sun look down and say, inglorious here he lies',
    'He that hath a trade hath an estate',
    'He that hath a calling hath an office of profit and honor',
    'At the working man’s house hunger looks in, but dares not enter',
    'For industry pays debts, while despair encreaseth them',
    'Constant dropping wears away stones',
    'By diligence and patience the mouse ate in two the cable',
    'Little strokes fell great oaks',
    'Employ thy time well if thou meanest to gain leisure',
    'Since thou art not sure of a minute, throw not away an hour',
    'A life of leisure and a life of laziness are two things. Do you imagine that sloth will afford you more comfort than labor?',
    'Trouble springs from idleness, and grievous toil from needless ease.',
    'Many without labor would live by their wits only, but they break for want of stock',
    'Industry gives comfort, and plenty, and respect: fly pleasures, and they’ll follow you',
    'Keep the shop, and thy shop will keep thee',
    'If you would have your business done, go; if not, send',
    'He that by the plough would thrive, Himself must either hold or drive.',
    'The eye of a master will do more work than both his hands',
    'Want of care does us more damage than want of knowledge',
    'Not to oversee workmen is to leave them your purse open',
    'In the affairs of this world men are saved not by faith, but by the want of it',
    'Learning is to the studious, and riches to the careful, as well as power to the bold, and Heaven to the virtuous',
    'If you would have a faithful servant, and one that you like, serve yourself',
    'For want of a nail the shoe was lost; for want of a shoe the horse was lost, and for want of a horse the rider was lost'
  ];
  return quotes[Math.floor(Math.random()*(quotes.length))];
}

function addFranklinQuote() {
  var tbl = document.getElementById('siteTable');
  if (tbl) {
    var quoteBox = document.createElement('div');
    quoteBox.innerHTML = franklinQuote();
    quoteBox.style.fontSize = "16pt";
    quoteBox.style.backgroundColor = "#f9f7ed";
    quoteBox.style.padding = "1.5em";
    quoteBox.style.position = "relative";
    quoteBox.style.width = '500pt';
    tbl.parentNode.insertBefore(quoteBox, tbl);

    var quoteName = document.createElement('div');
    quoteName.innerHTML = "-- Benjamin Franklin";
    quoteName.style.fontSize = "10pt";
    quoteName.style.position = "absolute";
    quoteName.style.bottom = "0";
    quoteName.style.right = "0";
    quoteBox.appendChild(quoteName);
  }
}

addFranklinQuote();

Greasemonkey really is as simple to use as it sounds. You give it a script and the URL’s to which it applies. When you browse to a page that matches the URL, the script is executed. For this one, it was a simple matter of adding a DOM element in the right place.

Some scripts are meant to be loaded on all pages, such as a script that makes it possible to use shift to quickly check or uncheck a bunch of checkboxes. If you’ve heard people complain about the Greasemonkey overhead, it’s probably because they’ve run a bunch of these utility scripts that run on all pages. A script or two that are browser-wide, with the rest of the scripts only running on a single site shouldn’t slow things down much.

To install, first install greasemonkey. Then, find the greasemonkey folder (gm_scripts) in your profile directory and save the above code into a file called “redditquotes.user.js”.

UPDATE (2007-07-17): After searching for ‘sliding doors css “dead space”‘ I found that someone already solved the problem without using JavaScript.

About a year ago I read Sliding Doors of CSS on A List Apart. While I admired the elegance of the design, I found the dead space on the left side of the tabs to be annoying.

The problem comes down to not being able to wrap an individual anchor tag around a list item tag and have it work. The anchor tag had to be put inside the list item tag, and try as I and the author might, it couldn’t be made to include the entire tab. The left side of the tabs were unclickable, as can be seen in the example.

The other day, I got the idea to fix the problem with JavaScript. I could make the list item trigger an onclick event. I could also make it show a hand cursor when hovering over the list item. The hand cursor thing could be done with CSS, but I like doing it in the JavaScript better, because if somehow the JavaScript code doesn’t execute properly, it won’t show a hand cursor in an area that’s not actually clickable.

I use the following JavaScript code, which relies on the JQuery library, to make the dead space clickable. On the first try I had the whole page flicker in Firefox when part of the anchor was clicked (the part that wasn’t dead space before). I tested it on the old page and it didn’t have the whole page flicker issue. So I figured out that it was probably a result of both the link and the javascript being triggered, and I added an event for the anchor to tell it not to trigger the dead-space event if the user clicked on the anchor.

clickedAnchor = false;

function fixDeadSpace(headerDiv) {
  var items = $('li', headerDiv);
  items.css('cursor', 'pointer');
  items.click(function(arg) {
    if (! clickedAnchor) {
      window.location.href = $('a', arg.target).attr('href');
    }
  });
  $('a', headerDiv).click(function() { clickedAnchor = true; });
}

$(function() {
  fixDeadSpace($('#header'));
});

To use, make sure the JQuery library is available, and add the above in a script tag. Here is the example with my code added, and different query strings in the links.

It behaves just about the same as if the left part of the tab were part of the link. The only difference that might be noticeable to a very small number of users is that when you hover over the area outside the anchor tag, the location isn’t shown in the status bar.

Recently I was hanging out at a coffee shop when a European tourist approached me and asked, “Excuse me, is there a wireless signal here?” I said “Yes.” After a little hesitation, due to her lack of fluency in English, she asked, “Free?”, and I said “Yes” again.

It occurred to me that she might not be that fluent in English, but knew how to ask if there was a wireless signal. It’s an important thing to learn, because an Internet connection is one of the most important tools for travelers (for me it comes only behind clothing, money, and identification).

My, how the world changes.

There has been no shortage of great writing on Microsoft’s patent strategy announced by Steve Ballmer on Monday. It’s a little hard to find, but it’s there. An interesting comment I found today (emphasis mine):

MY CHALLENGE TO MICROSOFT is that, if you’re just enforcing the law, go ahead and sue all your closest partners first. Start with Mainsoft, then find a list of all your gold partners and just work your way down. Maybe look up all the MVPs and find out who they work for, and make sure their companies get hit as well.

Also, find all the startups you’ve purchased over the years (e.g. Hotmail) and find the original owners and sue them retroactively. I don’t know if that’s possible to sue the Hotmail founder for using linux way back–but if it can be done, it SHOULD BE.

After that’s all cleared up, then you can go after the rest of the industry, like IBM, Red Hat, Sun, Oracle, etc. Fair’s fair, after all.

Posted by Peter {faa780ce-0f0a-4c28-81d2-3667b71287fd} on Tuesday, May 15, 2007 to the Joel On Software forum

One of my favorite web apps for finding news is TailRank. TailRank indexes thousands of blogs, and shows news that is that is being discussed by lots of legitimate bloggers. On their page, there are a bunch of stories, each with one main blog and a sampling of other blogs that reference the story. If you click on a link, it shows all of the articles that were grouped with that story. Usually, on pages that make the front page, there’s somewhere between 5 and 50 links to blog entries per story. Things that lots of bloggers comment on tend to be interesting. For example, today I found the following articles:

Each of these has links to a bunch of blog entries where different bloggers weigh in about the stories. Some of the stories attract blog posts where arguments are made. Others attract blog posts where people uncover different tidbits of information. Most are a little of both.

There are other things to like about TailRank — it has a great UI and is based on great technology. There’s a lot of information to be had on the front page. This is made possible because TailRank is well-cached. It’s very smart about which posts it lets into the system, and it keeps out many poorly-written and spammy blog posts. The UI is beautiful, from an aesthetic standpoint. The colors are great and it’s uncluttered. There are visual snapshots of each post. All around it’s an amazingly neat product. For what it does, it does a great job.

The founder has done a very good job of setting up infrastructure and putting together a programming team with a minimal investment. At first, according to him in a podcast he did (which also contains information on the caching), it was just him and he did some outsourcing. Now, according to an article linked to on the TailRank blog, he’s got one developer working with him in person in San Francisco. They’ve just released an API for using their blog search engine (short article).

Since I’ve been spending too much time on reddit, I have started using TailRank more, because a higher percentage of its articles are interesting. I think this is because reddit lets people frivolously increase the ranking of stories that they agree with, even if they aren’t interesting. To write a decent blog post about a subject takes time.

Another nice thing from a productivity standpoint is that it lacks comments in the reddit/Digg sense. It is in itself, focused on comments, though. It is a bit more difficult to write comments. You have to have a blog with interesting content and get it recognized by the search engines.

In my opinion it’s the best way to write comments, though. The person on whose site you’re commenting can’t delete your comment, since it’s on your on blog. They can delete a trackback, but they can’t delete it on TailRank. It also makes it easy for other people to find what you’ve written. And, of course, it’s better for marketing, since it brings people to your website.

I just read an article calling for a way to get an AST for Ruby code from within Ruby. I think it’s a great idea, and I think static analysis, code manipulation/refactoring are great reasons to support such a thing. Another consequence would be macros, which are a more controversial feature. The only downside I can think of is that it could be misused, and to leave out a feature for that reason would go against the Ruby philosophy, in my opinion. One of the regulars at the Phoenix Ruby Users’ Group argued against using a dumbed-down “teaching language”, saying that when you suggest using a language you don’t want to use yourself, you’re talking down to the learner. I agree. I think the best way to keep people from misusing features is not to remove the features, but to educate them. People in the Ruby community have always done a good job of making sure there’s lots of good example code out there, and giving constructive criticism when someone posts a bad example.

While the reasons in the article are enough, I can think of another good reason for having AST support — having the ability to constrain code to a certain set of features. There would be two different uses for this:

  • Running code from an untrusted source – This could include web template designers, or even users. Ning is an example of a site that lets users run their own code — but there is a huge overhead to facilitate this and to sandbox everything. If it could be verified that code doesn’t do anything dangerous, I think a new type of Web app plug-ins would emerge. Instead of having to set up an app on a separate site and use REST or SOAP to communicate, people could just throw together a little script in a domain-specific language. One idea I have for this sort of technology would be a Flickr for html and image generators (like ajaxload.info).
  • Enforcing decoupling – When managing a large software project, I think it would nice to specify which classes do what, and have it enforced. Maybe there is some class that’s supposed to be all about math, but that goes in an application that gives output to users. To keep math programmers from putting presentation logic in mathematical code, you could constrain them to a DSL that doesn’t have strings. Or, you could keep template programmers from doing networking code. The check could be done at runtime, or commit time, with plug-ins to the version control system.

There is a Perl library that parses Perl, but it would be nice to have one for Ruby that’s written in C and optimized for speed, and that with certainty matches up to what the interpreter understands.

I think that once an AST implementation was built, something like RSpec could be created which does compile-time or commit-time analysis. That would be cool.


Watch Dexter, Anybots, Inc.‘s self-balancing robot. Then watch the video of Honda’s Asimo robot walking and then falling down while attempting to climb stairs (I know they’ve had successful stair-climbing demonstrations since). Quite a contrast, isn’t it? Dexter’s walk looks like a human walk, a pretty feeble human, but a human walk. The Asimo robot’s walk looks like a souped up robot’s walk.

Both robots have their advantages. I’d like to see Dexter get the ability run off battery power. It would also be interesting to see other combinations of the two types of robots. But I will always remember Dexter as he is right now when I think back to the day that I first saw a self-balancing biped robot.

Valentine’s Day was fairly uneventful for me this year, but humankind made significant progress that day. Trevor Blackwell, a very smart man and a friend of Paul Graham, got his robot, Dexter, to walk with dynamic balancing.

The video is one of the most amazing things I’ve watched in my life. It was like the first time I saw a video of Apollo 11 lifting off. Its heroic effort to walk like a human walks, and to stay up on two feet, is amazing to see. I can see Trevor Blackwell’s effort in the robot’s movement. It looks like the robot is feeling the moment.

It’s a must-see.

Trevor’s creation is at Anybots, Inc., a company he founded that develops robot software. They have a website, and they’re hiring. A requirement in the “Join Our Team” page is hubris — one of the three great virtues of programming.

Another Steve Jobs quote (via SvN):

Most people make the mistake of thinking design is what it looks like. That’s not what we think design is. It’s not just what it looks like and feels like. Design is how it works.

I love how he uses first-person plural here (presumably by “we” he means Apple). It’s part of his Reality Distortion FieldWP. I think Apple employees have a strong sense of “if you weren’t great you wouldn’t be working here”. Sure, not all Apple employees are great for the company, but the feeling is very encouraging to those who are, and it leads many people to achieve great things.

Code Completion is a nice IDE feature that, for example, shows a list of methods for an instance of an object. It’s called IntelliSenseWP in Microsoft Visual Studio WP; in XCodeWP it’s just called “Code Completion”. It’s a very fast and user-friendly way to look up methods — while editing JavaWP in XCode, as soon as the user enters a period after a variable name, a list pops up, and as the user types it continues to narrow it down based on the first few letters. Documentation may also be displayed.

While XCode and most Java and .NETWP IDE‘sWP support this well, it’s a bit more difficult to implement for dynamically-typed languages like PythonWP and RubyWP. This is because of the difference between dynamic and static type systems WP. In a static type system, the type is determined at compile time, so the IDE can compile the code on the fly and find out the type. In a dynamic type system, the type is determined at runtime. Since running code can make changes to the system, such as deleting files, code can’t simply be run by the compiler to find out the type. Also, the type of a variable can vary, depending on a program’s input.

IDE’s for dynamically-typed languages implement Code Completion by examining the code. In a dynamic language, however, it’s impossible for an IDE to make a perfect guess as to which type a variable will be, in a given line of code, or which of several types it could be. It’s possible to let the user tell the IDE what type it’s expected to be. By guessing what type a variable has and letting the user override the guess, an IDE can have pretty good Code Completion for a dynamically-typed language.

One issue is, however, how does the IDE remember the user’s setting? Is it in a project file? I don’t really like having information for a file stored in a project file, since when the file moves between projects, settings are lost, or you have to go through the IDE’s way of moving the file between projects. Another possibility would be using a dot file (e. g. .foo.rb.ide-options) in the same directory. This is the way jEditWP stores bookmark settings. I don’t like this option because since they’re hidden I’m always forgetting to move them, and because it’s a pain to delete both the file and the bookmark file at the same time (I don’t like typing something like rm *foo.rb* because it will include baz_foo.rb). That leaves a couple options – including it right there in the source file or using a different naming scheme. This is easy to move around, but I’d rather keep these mundane details out of the source file.

This leaves using a different naming scheme. Perhaps foo.conf or foo._name_of_ide_. Whenever python runs a module, if it can, it automatically compiles it to bytecode and places it in a file with the same directory and name but with a different extension (pyc vs. py). I find that I have no problem with .py and .pyc showing up in my source directory. It’s nice to know that it’s byte-compiling it, and it’s easy to move around and delete (just use a wildcard expression like foo.*).

There’s no reason the metadata file can’t include all kinds of other things. I would want it to be extensible, and to include such things as bookmarks as well as Code Completion hints. This information could be stored as XML, YAML, or (my favorite) an S-Expression. Perhaps limiting it to things that only happen in the IDE would be a good idea, or maybe it could include instructions to the compiler to improve performance as well.

Another thing needed is a way to identify a variable inside a source file. I think the most elegant way would be a path containing the scope it’s in and the name of the variable. This would be something like my-namespace/my-class/my-method/param/bar. In an S-Expression format with the type and a construct for entering several in the same scope it could be something like:

(with-scope 'my-namespace/my-class/my-method'
  (specify-type 'param/p' 'Person')
  (specify-type 'local/brother' 'Person')
)

This would declare the parameter my-method and the local variable brother to be of type Person.

Finally, a quick way to declare the type in the IDE would be useful. I would like a right-click menu that goes something like this:

Popup Menu
+(other options…)
+Code Completion Type
++Auto
++(recent options)
++Custom…
+(other options…)

The Auto option would go back to having the IDE guess the type of the object. On a related note, I really like “auto” options that there are in office applications. It makes it really easy to say whether you want to stick with whatever the parent options are or specify your own options.

I have visions of a Lisp dialect with a great library and a great IDE getting a bit of a following and creating lots of LISP jobs. I think good support of code-completion while still having run-time typing, a dull color for parens, and built-in performance analysis WP tools (as Paul Graham suggested) would generate a lot of interest.

Thanks to Eliazar for the idea of using superscript to link to Wikipedia and other online resources.