TryParenScript.com

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.

View Comments


In response to "A JavaScript Function Guard"

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!

View Comments


My Notes from John Resig's "jQuery Hack Day" Talk

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:

Testing Mobile JS

John has been researching mobile space lately.

Cross-browser mobile dev is crazy

A simple goal

Three questions:

  1. What platforms and browsers are popular?

  2. What browsers are capable of runnning the "modern web"?

  3. ?

Who has the best stats?

Lack of Info

Symbian more popular among consumers than all others, despite lack of developers.

Hardest Question

Opera Mini most popular mobile browser (by use)

What version of each browser is popular?

Testing Strategy

Drawing a line

Testing Browsers

Simulators

Automate Testing

Platforms

Phonegap!

Summary

What devices to buy?

Questions

View Comments


Announcing Pocco

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!

View Comments


Yet Another Lisp

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!

View Comments


« Older Entries

Recent Entries


TryParenScript.com

On July 23rd, 2010


In response to "A JavaScript Function Guard"

On July 19th, 2010


My Notes from John Resig's "jQuery Hack Day" Talk

On July 5th, 2010


Announcing Pocco

On June 29th, 2010


Yet Another Lisp

On June 25th, 2010


Recent Happenings: All Play and No Work

On June 21st, 2010


Arguments.callee considered extraneous

On June 2nd, 2010


Javascript, "bind", and "this"

On May 20th, 2010


Class-Based Views and Django

On May 19th, 2010


Introducing Zoolander

On May 2nd, 2010


Creative Commons License

Fork me on GitHub