The timing would have been close, with Python 1.2 out in 1995 too. And there’s a lot of similarity between the languages: dynamic typing, first-class functions, eval() (and somewhat bizarre treatment of whitespace) … it isn’t hard to imagine a Python VM running in the browser with access to a global “document” and “window” object.
Whenever two pieces of unconnected code communicate, the way they communicate has to be agreed upon, and the two parts must stay in sync or communication fails. One way to do this is to define a protocol describing the communication between them. I’m fine with writing protocols but this generally just means you now have three parts to keep in sync: the client implementation, the server implementation and the code itself. Machine-readable descriptions like XML Schema and WSDL attempt to fix part of that problem … but wouldn’t it be nice to just declare this stuff just as functions which call other functions?
@runs_on_the_server def get_user(username, password) return db.tables['user'].select(username=username, password=password) @runs_on_the_client def handle_login(form): user = get_user(form.username, form.password)
The python compiler can see that a function which runs_on_the_client is calling a function which runs_on_the_server, and can go away and create some kind of RPC interface for us without bothering us with the details. There’s an argument (see above) that this abstracts away all the HTTP goodness, but that, to me, is the whole point.
One criticism of this is that you might get confused as to what code is running where. For this reason, I think some very explicit mechanism like the decorators shown above is necessary. Writing the server and client code in different languages is not sufficient to enforce good security in any case, as any fan of SQL injection can tell you …
It is pretty common that you want to validate a form field on the frontend, to save a whole lot of round-trips, and also on the back-end, because the frontend can’t be trusted. This isn’t hard to do if your validation step is just a regexp – and I’ve written code which depends on exactly this – but not all validation steps can be sanely expressed as regular expressions. If you’re going to have to write a validator function, you should only have to write it once:
@runs_on_both def validate_number(n): return n % 13 != 0
“But how hard can it be to write _that_ twice”, you say. But the point is, if it is only written in one place then it can’t get out of sync between _this_ version of the client and _this_ version of the server, resulting in either the server accepting something the client shouldn’t be allowed to send or the client sending the server something it will only reject.
Assuming for the moment that this is a worthwhile goal, what progress has been made towards it?
I can’t help thinking that one of the Lisp family would be a good candidate too.
But, sticking with Python:
Obviously, a Python VM plugin would be one possibility, but that would have to be supported for multiple browsers and no-one likes installing plugins anyway so getting any kind of traction would be near impossible.
Conceivably, a Python to JS converter could provide a “beachhead” for the use of a Python plugin … or, indeed, for a total replacement of the browser!
I ended up writing a bytecode to JS converter, it is pretty sketchy but I put it on github anyway: Tropyc.
See also Zombie, a rethink of some of these ideas.