Hello, I'm Nick Fitzgerald. This is my weblog. You can also check out my shared items from Reader and code on GitHub. Feel free to contact me about whatever.
July 23rd, 2010
I got a quick and dirty, first-iteration of TryParenScript.com up and running!
TryParenScript follows in the footsteps of TryRuby.org, TryHaskell.org, and TryClojure. It provides a basic ParenScript REPL inside your browser. Type ParenScript code in, see the compiled JavaScript, and then view the result from evaluating that JS.
Common Lisp was such a pain to set up behind Apache that I ended up coding both front- and back-ends in ParenScript by taking advantage of Node JS on the server. (Don't you like how the technology that has only started to gain traction in the last year was easier to deploy than the language that was used to write one of the early interpreters for JavaScript?)
This is still a work in progress! That means you shouldn't expect a flawless experience yet.
For example, the biggest reason to use ParenScript is to harness the power of macros in your client side code. Unfortunately, because the macro-expansion is run on my server, and I haven't figured out a good way to sandbox Common Lisp, I can't let anyone define custom macros yet. If I did, anyone could run arbitrary code on my server.
Also, and this should be fixed reasonably soon, because of the way I am
(ab)using jQuery.globalEval, function declarations are screwed up. It is
expected that the following form creates a new, global function.
(defun foo (x) (return (+ x 1)))
However, what ends up getting evaluated in jQuery.globalEval is equivalent to
this:
window.__tryps_return = function foo(x) {
return x + 1;
}
As you can see, Function Declarations are accidentally transformed in to Named Function Expressions, which don't leave a footprint on the scope they are created within (except in IE, because of a nasty JScript bug). As I said, I plan to fix this one very soon.
Despite those two shortcomings, I am very pleased with the progress I have made so far! The code is hosted for the world to see on GitHub, please take a look at the source! This is my first "real" ParenScript project, and I would love to get some feedback.
July 19th, 2010
Angus Croll just wrote a blog post on "function requests [where] the function only gets invoked after you’ve finally stopped requesting it". This started out as a comment over there, but quickly grew a little long, so I am just going to post it here. Go read his post to get a little context, it's worth your time.
I have used this pattern multiple times, but I never realized I should generalize it. Kudos, Angus! Great code; great read.
Now to the nitpicks :)
Angus implemented this utility as a prototype constructor, but my opinion is that using a closure is more elegant. It takes less lines of code to implement, and more importantly, less lines of code to use.
// Angus' version, with a bug
var resizeMonitor = new FunctionGuard(function (event) {
if (typeof window.onresizeend === "function")
window.onresizeend(event);
}, 100);
window.onresize = resizeMonitor.run;
But, it's actually worse than that to use, because you must bind the run
method to the resizeMonitor object. If you don't then this will refer to the
global object, rather than the resizeMonitor.
// Bug-free version
var resizeMonitor = new FunctionGuard(function (event) {
if (typeof window.onresizeend === "function")
window.onresizeend(event);
}, 100);
window.onresize = function () {
resizeMonitor.run.apply(resizeMonitor, arguments);
};
Making this utility a function that returns another function with state hidden in a closure is easier for end-users.
// Same example, using my version
window.onresize = doLastCallAfter(100, function (event) {
if (typeof window.onresizeend === "function")
window.onresizeend(event);
});
Simulating an onresizeend event, was definitely a cool example. The first
thing that I thought of was to automatically logout an inactive user, and
protect their privacy.
var logoutAfterInactivity = doLastCallAfter(600000, function () {
window.location.href = "http://example.com/logout";
});
document.body.onmousemove = document.body.onkeydown = logoutAfterInactivity;
And finally, here is my implementation.
function doLastCallAfter(quietTime, fn, context /*, fixed args */) {
context = context || this;
function slice(thing, i) {
return Array.prototype.slice.call(thing, i || 0);
}
var timer, fixedArgs = slice(arguments, 3);
return function (/* dynamic args */) {
var dynamicArgs = slice(arguments);
if (timer !== undefined) clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, fixedArgs.concat(dynamicArgs));
}, quietTime);
};
}
Awesome utility, Angus!
July 5th, 2010
So late on the night of the fourth I happened to check my email and find out that Amazon.com was throwing a "jQuery Hack Day" today and admission was free (so was the pizza). Awesome! I was in Seattle over the holiday weekend for all of one and a half days, and this just happened to fit my schedule perfectly!.
John Resig gave a talk on mobile web development and testing, and I took notes on my laptop the whole time. He promised to put his slides up on his blog, but just to tide you over, here are my notes:
John has been researching mobile space lately.
Cross-browser mobile dev is crazy
not as bad as it used to be
2 to 3 years == golden age of web dev on mobile
A simple goal
Make jQuery work on the most popular mobile platorms and browsers
Really hard to even define scope of this problem
Three questions:
What platforms and browsers are popular?
What browsers are capable of runnning the "modern web"?
?
Who has the best stats?
Gartner: Well respected, knows sales info well
StatCounter: Billions of hits per month
Admob: Decent for specific platforms (Andriod, iPhone)
Even with all this, very little info is available
Lack of Info
Hard to find data, so developers develop for what is in front of them:
iPhone
Android
iPad
BlackBerry
This is bad, ignoring the actual market representation
Symbian more popular among consumers than all others, despite lack of developers.
Hardest Question
What version of those platforms are actually popular?
No one knows (or at least Gartner won't tell)
Opera Mini most popular mobile browser (by use)
What version of each browser is popular?
Considered to be competitive advantage to keep it private
Apparently Yahoo! knows
Testing Strategy
Draw a line in the sand and decide what to support, and what is too old.
Buy devices, download simulators
Automate testing (TestSwarm!)
Drawing a line
Use Yahoo!'s graded browser support technique
Qualify which browsers you will support (actibely test against) and give them a grade
A = Full support, C = Fallback to old site, Other = Assume full support
Testing Browsers
Two options:
Buy devices
Download simulators
Simulators good for most automated testing
Any sort of interaction testing will want to also be done on the actual device!!!
Simulators
Available for most mobile platforms and browsers
Automate Testing
Once you have simulators or devices, interact with them as little as possible
Automated test execution important
TestSwarm developed for exactly this purpose
Platforms
Moves so fast! Even a couple months is a big difference!
Symbian S60
Nokia
Webkit in v5.0 and up
simulators available from nokia.com
Nokia just announced they are killing Symbian in favor of Meego!
iPhone OS
Almost all users are on the latest OS version
Safari 4
1 gotcha: no fixed position support (difficult to implement toolbars)
Reccomended TouchScroll library
Simulator is part of the iPhone SDK
iPad and iPhone views to toggle
No 2.X emulator!
BlackBerry OS
Enormously popular, still growing!
Switching to WebKit soon (thank goodness)
Anything older than 4.6 is really frightening, 5.0 is decent
Simulator downloads on their dev site
Doesn't support internet, need "internet simulator" :-/
Android
Gaining marketshare at incredible rate
Predicts overtaking iPhone in the next year or so
Mobile manufacturers jumping on it because it is free.
Huge ammount of fracturing on version
Opposite of iPhone
people aren't upgrading (a lot of blame on the mobile provider, not google)
Going to be around for at least ~2 more years
Simulator easy download
Windows Mobile
6.5 uses IE6 as rendering engine
Next release is using IE7 (!)
At least we all know the quirks by now (yay...)
6.1 ships with IE4, no way its getting supported
6.5 simulator easy download
WebOS
Not clear where its future is going
Webkit, so it is easy to support
1.4 simulator ships with 1.3 browser — WTF?
Only way to test 1.4 browser w/ physical devices
Maego (being renamed as Meebo)
Nokia 900 only device (not even phone)
Nokia is moving to this
Gecko based browser in Maego, not sure where Meebo is headed
"Very important, very soon"
Opera
Not platform, but browser is everywhere
Two browsers:
Opera Mobile:
Opera Mini:
"Glorified bitmap viewer"
No JS on client
Let JS run 2 seconds on server
Interaction is on the server
Runs pretty much everywhere
jQuery UI going to at least "look right"
Simulator is cross platform
Fennec
Maemo and Android
Equiv to latest Firefox
Faster than the built in browser!
Netfront
Used on Playstation and N-Gage
Not worth the time of day
Phonegap!
Not platform, more environment
jQuery will work with phonegap
Use webkit to make webapps for app stores
Summary
Roughly, this is equivalent to what you are supporting:
Opera 9.5, 10
IE 6, 7
FF 3.5+
Safari 2, 3, 4
And BlackBerry
Don't assume since something is Webkit (for example) other WK browsers will work!
Test!
Simulate!
What devices to buy?
"A level" will cost ~$2,500:
iPhone 3GS
Or iPod Touch
iPad
Nokia
...
"B level" will cost ~$2,000
Questions
Why do carriers restrict upgrades?
They like knowing exactly whats running?
Known evil
Amazon employee asked about BB:
BB has JS disabled by default
Scary message when you try to use JS
Do the android carrier specific changes affect the browser?
Not really, mostly the UI and "skin", not functionality
So far, who knows in the future
Much worse for native apps than web apps! Many little differences between Android versions there
June 29th, 2010
Out of respect for the Pocoo team, I have renamed Pocco to Pycco to alleviate the ambiguities created from such similar names. Pocoo, thanks for creating Pygments and all the other cool projects you guys do! Here is Pycco's new github project page.
Pocco is a Python port of Jeremy Ashkenas' Docco. Pocco, like Docco before it, generates literate-programming-style documentation from your source files.
To see it in action, simply check out the github project page, which is the result of running pocco on itself.
To install, simply
git clone git://github.com/fitzgen/pocco.git cd pocco/ sudo python setup.py install
Bug reports welcome!
June 25th, 2010
I couldn't help it.
Between my current PL course and reading Lisp in Small Pieces off-and-on, I had to start writing my own Lisp again. I have named it Magritte, after René Magritte. So far just the basics are working. Pattern matching and destructuring, but no guards yet. Lambdas are a go, but the lexical scope is a little buggy still. No macros yet.
Here is the famed Y Combinator, in Magritte.
magritte> (defn (Y X)
((fn (procedure)
(X (fn (arg) ((procedure procedure) arg))))
(fn (procedure)
(X (fn (arg) ((procedure procedure) arg))))))
(((X) . #<CLOSURE # {BD7D315}>))
magritte> (def fact (Y (fn (f) (fn (n)
(if (eq? n 0)
1
(* n (f (- n 1))))))))
#<CLOSURE (LAMBDA (VALUES &KEY (BINDINGS NIL))) {BA383E5}>
magritte> (fact 3)
6
magritte> (fact 8)
40320
And here is a pretty typical definition of map, using pattern matching and destructuring.
magritte> (defn (map f ()) ())
(((F NIL) . #<CLOSURE # {B83C1D5}>))
magritte> (defn (map f (h . t)) (cons (f h) (map f t)))
(((F (H . T)) . #<CLOSURE # {BB4C0E5}>)
((F NIL) . #<CLOSURE # {B83C1D5}>))
magritte> (map (fn (x) (* x x)) '(1 2 3 4 5 6 7 8 9))
(1 4 9 16 25 36 49 64 81)
Currently, Magritte is written in Common Lisp. My plan is to get the interpreter to a decent level of quality, then write a Magritte -> Common Lisp compiler, in Magritte. Then we'll really be having some fun!
On July 23rd, 2010
On July 19th, 2010
On July 5th, 2010
On June 29th, 2010
On June 25th, 2010
On June 21st, 2010
On June 2nd, 2010
On May 20th, 2010
On May 19th, 2010
On May 2nd, 2010