Five short years

On Friday, October 22, 2010 I conducted a scientific experiment: if one URL shortener can make a URL shorter, then fifteen URL shorteners can make it reaaaally short. The results were quite as you'd expect: the resulting link was longer than source, and browsers would go into convolutions trying to resolve the chain of shortened shorteners.

2010 was a big year for people who thought it would be a good idea to make smaller URLs. All it took was a rudimentary knowledge of a hash map and an hour of coding and suddenly you had a viable startup on your hands. There are a lot of URLs out there, so the thinking went, and people need a place to make them shorter. Phase 1: Shorten URLs...

So now it's 5 years later, and I thought it would be interesting to see what become of that unraveling chain of hopes and dreams. Here they are, in reverese order of resolve-y-ness:

  1. http://bit.ly/6YuThD ALIVE. Correctly resolves to mrspeaker.net
  2. http://goo.gl/oZrv ALIVE. Correctly resolves to mrspeaker.net
  3. http://tinyurl.com/34ve64r ALIVE. Correctly resolves to mrspeaker.net
  4. http://w8jyd.tk Service: ? Link: DEAD. I'm not even sure how this one ever worked!
  5. http://nik.im/4iB1 DEAD. Domain squatter-ed
  6. http://vbly.us/2ew7 ALIVE. "The internet's first and only sex-positive url shortener".
  7. http://alturl.com/gv49t ALIVE "Free short URLS since 1999"
  8. http://is.gd/gaWwV Service: ALIVE Link: DEAD. This looks reasonable though: "Link Disabled because of T&C violation".
  9. http://xrl.in/6jbi DEAD. Domain squatter-ed
  10. http://wurl.ca/?r=4oe DEAD. "Wurl Redirection Service is permanently closed."
  11. http://eweri.com/Eh1u DEAD. Domain squatter-ed
  12. http://snurl.com/1bmlco ALIVE. "Snippety snip snip". Whatever that means.
  13. http://lnk.nu/snurl.com/1g6o DEAD. Redirects link to a google.com 404.
  14. http://liteURL.com/?116051 DEAD. Domain squatter-ed. Also, my office router warns "Gateway BOTNET Filter Alert".
  15. http://linkzip.net/F/4JC ALIVE. Resolves correctly, but the service has a lovely broken image gif as a logo now.

I was quite impressed to discover that 8 out 15 still resolve the links correctly (counting the T&C violation). That means that only around half of world's shortened URLs now 404: much better than I thought! I'll revisit this post in 2020, so be sure to come back then to see how it goes - just keeping this handy 8x shortened link lying around. I've run it through all the remaining contenders, so I see no reason it won't resolve in another 5 years.

mrspeaker's head in a monitorYou find yourself at the entrance to the Hompage of Mr Speaker. In a darkened corner sits a trunk containing HTML5 games and some JavaScript tidbits. In a dark corner you spy a Twitter account. Exits are North, East, and .

?> _

Explostyx: explody 3D french fries

Some more crazy 3D action in the form of Explostyx: explody 3D french fries thing. It's what happens when you make one simple thing and then just repeat it a whole stack of times. Like all good pop art.

It's using Three.js, and 100-odd lines of ES2015 - so it's a pretty simple example if you want to delve into either.

explostyx

Wanna do new JavaScript + React?

Here's the "easiest" way to get started with the latest version of JavaScript (so much new stuff in es2105!) and the most popular kid (for this week, at least) in the JS framework playground: React.

This approach uses the wonderful new JSPM package manager... so if you're not willing to place your bet on this particular horse, then head over to WebPack land to see if they have a similar guide. Also, if you want to see the final product - here's my "ES2015+React boilerplate".

  1. Create a new project with jspm install (and install JSPM if you haven't).

  2. Hit enter over all the defaults, except for Transpiler: traceur/babel?. Change this to Babel. It's more cool this week, and supports JSX.

  3. But it doesn't support JSX by default. To allow it, we need to tweak the babelOptions in the config.js file. Add the option "blacklist": [] to remove react from the blacklist.

  4. Next we need a simple index.html page. Inside the body tag:

    <body>
      <div id="app"></div>
      <script src="jspm_packages/system.js"></script>
      <script src="config.js"></script>
      <script>
        System.import('src/main');
      </script>
    </body>

    This loads the "System" module loader polyfill so we can load modules. The config file specifies a bunch of modules to load (such as React!). Finally, we do our own System.import and call our own file at /src/main.js.

  5. Add a script at /src/main.js. Make it look like this:

    import React from 'react';
    
    export default React.render(
      <div>Hello World </div>,
      document.querySelector('#app')
    );
  6. Serve it up. Use the simple web server of your choice (I like http-server) to serve the page, and test all is well.

Phew, quite a lot still - but worth it to get all the magical goodness. Plus it's all in the boilerplate repo if you don't want to do these steps every new project.

Alien vs Joy Division

Above is from "Alien" released in May 1979. Below is from Joy Division’s "Unknown Pleasures", April 1979.

Screenshot from Aliens, contrasted with the classic Joy Division album cover

Announcing JS.scala v0.1

I'm pleased to announce the initial releas of JS.scala. JS.scala compiles JavaScript source code to Scala source code, allowing you to write your web application entirely in JavaScript! Finally, the expressive power of JavaScript available on the JVM via Scala (some call it "the bytecode of the JVM bytecode").

How does it work? Well, given the JavaScript input:

const a = 42
const b = "Hello, World"
const sq = x => x * x
const dsq = x => {
  const dx = sq(x)
  return dx * dx
};
const d = dsq(a)

const exclaimer = {
  apply: name => name + "!"
}

exclaimer.apply("Hello, World")

We get the lovely Scala output:

val a = 42
val b = "Hello, World"
def sq (x:HandHolder) = x * x
def dsq (x:HandHolder) = {
  val dx = sq(x)
  dx * dx
}
val d = dsq(a)
object exclaimer {
  def apply (name:HandHolder) = name + "!"
}

exclaimer("Hello, World")

You can then compile this and deploy to production.

What about types?

Those who rely on their IDE for autocompletion, or their compiler for type-checking get nervous when they have to know the types of things, so the next step is to add Flow type inference (https://github.com/facebook/flow) types to AST to restrict the expressive power of JavaScript, but export valid Scala.

That's for v0.2 though (keep an eye on the repo)... for now it just replaces types with a "HandHolder" placeholder.

Oculus Rift Reddit Internet Explorer

Recently both Firefox and Chrome released VR-enabled version of their browsers. Just as Lawnmower Man predicted.

I decided to test them out with the Rift, by hacking together "Mr Speaker's Internet Explorer" (or the repo): It loads any ImgUr images in a sub, and finds related subs mentioned in the "about" info.

gallery view

To load new subreddits, either hit "/" and type the name of your favourite time-wasting spot, or, better, look for the small obelisks around the space that contain a "/r/sub" title. If you look at these and hit enter, it will load automagically - so you can walk around exploring the space.

load sub view

I'm still just messing around with it, but it's kind of useful/interesting enough that you can almost feel the metaverse approaching.

“let” is the new “with”. But good.

The ES2015's let and const keywords give us better (actually useful!) control over variable scope. We can use this to write code in a more terse, cleaner manner.

Mozilla's original implementation of let had support for non-standard let blocks that looked like this:

let (x = x+10, y = 12) {
  console.log(x+y); // 27
}

Let blocks also allowed us to define blocks similar to how we used to write with in the olden days: let (pos = obj.position) { pos.x++; }. I don't know why this got the boot from the final ES6 spec (I quite like the syntax), but we can recreate the idea using empty blocks and defining the variables like normal:

const stats = new Stats();
{
  const dom = stats.domElement;
  const style = dom.style;
  stats.setMode( 0 );
  style.left = "0px";
  style.top = "0px";
  document.body.appendChild( dom );
}

Thanks to const and let behaving sensibly, the dom and style are only defined inside the block. This gives us all the power of the let block, and none of the problems of the old school with statement.

Mac service: open iTerm at selection path

Opening the current folder or file path in iTerm is something I want to do a lot. The second time I ever wanted to do this I decided I should automate it. The 10,000th time I wanted to do this, I actually did automate it.

Here is an applescripted automator service to open the current selection path in a new iTerm window:

mac services list
Clicking on the option will spawn a new iTerm window, and cd to either the folder path, or the containing folder if it's a file:
path opened in bash

That's it. To install it, grab the Open iTerm to Path zip file and open the .workflow file inside. Open it in automator if you want to see the code, else just hit "install" and it will be available in services.

Also, if you want to change what shows up in your services context menu, go to prefs -> keyboard -> shortcuts -> services.

Annnd finally, if you just wanna see some code, here be it...

(Nearly) Getting Started with ClojureScript

UPDATE: Holy cow, they fixed the docs! Sooo, I don't know if it was directly related to this rant, but the quick-start docs now rock! So go forth and ClojureScript!

So you've decided to do your next pet-project in ClojureScript because Rich Hickey is awesome and the Web is awesome, therefore, Clojure on the Web must also be awesome. This article walks you through the many-and-varied steps of trying to get up and running with ClojureScript, by closely following the repo docs.

Hello ClojureScript popup

tl;dr: trolling ahead. Good intro documentation is critical if you don't want to scare off/annoy new users. Follow your own "getting started" docs without assumed specific knowledge and see if it's a nice on-boarding experience for your new community members.

Let's begin our adventure by googling "clojurescript". The most authoritive-looking link is to https://github.com/clojure/clojurescript. The repo doesn't seem to link to a webpage, so we'll assume this is it. The README becomes our first introduction to the world of ClojureScript:

"What is ClojureScript? ClojureScript is a new compiler for Clojure that targets JavaScript. It is designed to emit JavaScript code which is compatible with the advanced compilation mode of the Google Closure optimizing compiler."

Ok, there's the hook: It's new! It's Clojure! Something something about Google Closure! Whatever that is. It sounds like "Clojure", so it must be good!

The next most important piece of information is "Releases and dependency information"; telling us the latest stable release number, and something about "Leiningen" and "Maven". We only want to Learn ClojureScript so let's hope those things are unimportant for now. It's generally safe to assume weirdly-named third-party tools at the top of language repos are package managers. Anyhoo, the next part looks like it's for us: Getting Started.

Getting Started is exactly what we want to do! The first couple of links in this section shows syntax equivelants in JavaScript and Clojure and let us play with it online. That's fun, but figuring out the syntax is very low on our priorities for the moment - we need to be able to actually start a project before we write code, so the the third link on the page looks like a winner: the quick-start guide.

The "Quick Start" guide.

Nice, some direct instructions! First clone the ClojureScript repo somewhere handy and follow the instructions:

git clone https://github.com/clojure/clojurescript.git
cd clojurescript
./script/bootstrap

So we grabbed the repo then executed a random script that does something. Bootstrap things, presumably. It does say it's grabbing Google libraries that ClojureScript depends on. I'm guessing that when we figure out how to start a project we'll see if this needs to be done once per system, or if we have to clone the code for each new project and run it, or what not.

Notable tools

There are a few notable tools included: the first is a Local Clojure REPL. We all know that a REPL is the "Read-eval-print-loop" for entering commands and evaluating them. I guess we want a local Clojure REPL because ClojureScript must rely on it for something. Perhaps there is a remote REPL too? Probably need to go to the Clojure repo for that info. Anyhoo... it tells us to export an environment variable called CLOJURESCRIPT_HOME (and preferably make it permanent in your bash profile):

export CLOJURESCRIPT_HOME=$PWD

Groovy, now we're cookin'! Now we can start a "properly-classpathed Clojure REPL" ("properly-classpathed" sounds pretty impressive eh?). Let's run it:

./script/repl

This gives us a REPL!

Clojure 1.6.0
user=>

Lets test it out:

user=> (println "Hello World")
Hello World
nil

Running Clojure! Not exactly our goal, but seems like a good first step. Next up, it says "From within this REPL, start a ClojureScript REPL..." and then there is a stack of code that I hope we don't have to memorize and input every time we want to write some code:

(require '[cljs.repl :as repl])
(require '[cljs.repl.rhino :as rhino])
(def env (rhino/repl-env))
(repl/repl env)

The last line kicks off the ClojureScript REPL, and outputs:

user=> (repl/repl env)
To quit, type: :cljs/quit
Error: Namespace "goog.debug.Error" already declared. (goog/base.js#248)
Error: Namespace "goog.asserts" already declared. (goog/base.js#248)
Error: Namespace "goog.string" already declared. (goog/base.js#248)
org.mozilla.javascript.JavaScriptException: Error: Namespace "goog.string.StringBuffer" already declared. (goog/base.js#248)
  at goog/base.js:248
  at goog/string/stringbuffer.js:19
  at bootjs:1
  at cljs/core.cljs:10

Error: Namespace "goog.string.StringBuffer" already declared. (goog/base.js#248)
Error: Namespace "goog.debug.Error" already declared. (goog/base.js#248)
Error: Namespace "goog.dom.NodeType" already declared. (goog/base.js#248)
Error: Namespace "goog.string" already declared. (goog/base.js#248)
Error: Namespace "goog.asserts" already declared. (goog/base.js#248)
Error: Namespace "goog.array" already declared. (goog/base.js#248)
Error: Namespace "goog.object" already declared. (goog/base.js#248)
Error: Namespace "goog.string" already declared. (goog/base.js#248)
org.mozilla.javascript.JavaScriptException: Error: Namespace "cljs.core" already declared. (goog/base.js#248)
  at goog/base.js:248
  at cljs/core.cljs:9
  at bootjs:1
  at <cljs repl>:126

ClojureScript:cljs.user>

Hmm, maybe that's normal - who knows - it's giving us a different prompt now though, so let's test that one!

ClojureScript:cljs.user> (println "Hello World")
Hello World
nil

Kind of feeling a bit inception-y here, but hey... it's working and we've run some ClojureScript! Next up it says "Local ClojureScript REPL". Hmm. What did we just do then? I'm not sure what that last step was all about then, as it appears we can bypass it entirely and just type:

./script/repljs
To quit, type: :cljs/quit
org.mozilla.javascript.JavaScriptException: Error: Namespace "cljs.core" already declared. (goog/base.js#248)
  at goog/base.js:248
  at .cljs_repl/cljs/core.js:2
  at bootjs:1
  at <cljs repl>:126

ClojureScript:cljs.user>

Less errors too! And that prompt looks like what we ended up with at the end of the last step: so I think we can forget that mini-program above and just use this guy! Phew.

Hmm. Then it says "If you have Node.js installed". You know what? I DO have node.js installed....

./script/noderepljs
To quit, type: :cljs/quit
ClojureScript Node.js REPL server listening on 53639
ClojureScript:cljs.user>

Ooookkkay. The same-looking prompt as before, but it also says something about a server on port 53639. I guess we can ignore that for now. The docs say "In this mode, ClojureScript code will be compiled into JavaScript and executed by the JavaScript engine". Sounds good - but maybe we'll leave Node for the moment.

ClojureScript Compiler

So it looks like we're done with REPLing and on to the real deal. Compiling some code from a file: "Compile ClojureScript source files or projects to runnable JavaScript." Boom! Sounds awesome. The compiler is located in the bin directory:

./bin/cljsc

It says its convenient to set a CLOJURESCRIPT_HOME environment variable pointing to the ClojureScript root directory and to add $CLOJURESCRIPT_HOME/bin to your path.

We already did the first part in the "Notable Tools" section, so we should now add the `/bin` path:

export PATH=$CLOJURESCRIPT_HOME/bin:$PATH

And just to make sure things work:

$ cljsc
Usage: cljsc <file-or-dir>
  cljsc <file-or-dirv "{:optimizations :advanced}"

It then goes on to say "cljsc is convenient when a command-line tool is required or when a file or project only needs to be compiled once. While developing, it is much faster to use the build function from the Clojure (not ClojureScript) REPL."

Hmmm, there's a spanner in the works. The compiler was not what we were looking for all along. Perhaps? The Clojure (not ClojureScript) REPL was the first one we tried. Not sure why the ClojureScript REPL is no good, but I guess that's part of the reason they provide all those REPLs. To start the Clojure REPL we had to be in the clojurescript directory and run ./script/repl. Then paste this:

(require '[cljs.closure :as cljsc])
(doc cljsc/build)
-------------------------
cljs.closure/build
([source opts])
  Given a source which can be compiled, produce runnable JavaScript.

Obviously only the first two lines are the code, the stuff under the ------- is the result, so don't go pasting the whole thing in the REPL. I didn't do that, promise.

Using ClojureScript on a Web Page

Well, we didn't end up compiling anything above - so I'm still not really sure what the "build" thing does - but it claims to be "faster when developing" so, that sounds cool. Anyway, compiling stuff is old-school... it's all about using things in a web page these days, so let's get on with it.

"The following example shows the basic steps involved in creating a ClojureScript application and running it from a web page.". Hey hey! That also sounds pretty promising... I'm starting to wonder if we should have just got started here.

"The example assumes that you are working in the ClojureScript root directory." Hmm, strange sounding requirement seeing as we did all the classpath stuff - but hopefully it'll work easily in other directories too.

"In the example below, a function is created which will be called from JavaScript in a web page. The :export metadata ensures that this function name is not minified. The JavaScript function will be available as hello.greet."

Interesting - clojurescript must minify the generated JavaScript by default. The :export tag stops it munging up the name. I don't know why that's the default - maybe it makes sense, or is standard Clojure. Anyhoo, we'll just have to remember the magic export thing.

(ns hello)
(defn ^:export greet [n]
  (str "Hello " n))

Next up: "Save this code into a file named hello.cljs and then compile it to JavaScript."

From the command-line, you invoke the clsjs compiler from the "ClojureScript Compiler" section. There's also instructions for the REPL - you just have to do the steps from the last part on the clojure compile: require-ing the cljsc/build thing.

Both of them output the compiled hello.js files.

Unrelated warning: *DO NOT LOOK AT THE JAVASCRIPT*, it will make you cry a little inside. Transpiling is compiling to a similar level of abstraction - so, like compiling your F# code into Scala then running that generated code on your production servers. It works fine, but it doesn't mean Scala coders are going to enjoy reading it.

Anyhoo... Linking that from a html file with alert(hello.greet("ClojureScript")) runs some ClojureScript! We're on our way!

Running ClojureScript on Node.js

This section is just if you want to run directly from Node, as an alternative to running in the browser. That sounds fun, but let's stick to the browser for now and see if we can't get a better workflow in place. We can always come back to this later.

More about Compiling

"The cljsc tool, and the underlying build function, supports three levels of optimization and a development mode where no optimization is performed and each input JavaScript file is kept separate."

Oh, okay - that's interesting. The initial examples all assumed you were outputing for production, and there's some stuff we can do to make things more obvious while we're getting started. The "hello, world" function probably doesn't need to be production-ready so that sounds like a good idea.

By ommiting the :optimizations option, the JavaScript will be compiled into the working directory (which defaults to ./out) and write a dependencies file to hello.js." You need to cd into the samples/hello directory for this example, and run:

$ cljsc src '{:main hello}' > hello.js

If you want to do the REPL version then you actually shouldn't be in the samples/hello dir, but back in the clojurescript root directory so you can run the repl. Then you need to add back all the paths to make up for that:

(cljsc/build "samples/hello/src" {:main hello :output-dir "samples/hello/out" :output-to "samples/hello/hello.js"})

Compiling takes an eternity in web time (like, 10 seconds) because it generates a folder called out in the clojurescript directory that has a zillion dependencies. There's probably a way to do partial compilation or something like that though so we don't have to generate all the same old stuff, and wait 10 seconds every time we change something.

If you look at the files in samples/hello, you'll notice it's completely different from the hello.cljs version above: I think it's more of a complete project. There is a file called core.cljs which has a bunch of functions, and a folder called foo that demonstrates how how imports work. Or something.

There are two html files in the folder: hello.html and hello-dev.html. The first doesn't work, because the commands above don't have the "{:optimizations :advanced}" flag. The hello-dev.html throws the errors:

"goog.require could not find: hello" base.js:466:6
Error: goog.require could not find: hello

In the console, but the program appears to run - so, we'll take it. The production mode adds back in the "optimizations" flag, and does't specify the :main hello thing - I guess that must be implied in advanced mode.

$ cljsc src '{:optimizations :advanced}' > hello.js

The good news here is that running hello.html works perfectly, and no errors in the console!

We're done.

Phew, we made it to the end of the Quick Start section! We deserve a beer. I'm still not really sure what most of the pieces are for: the difference between the Clojure REPL, the ClojureScript REPL the Node ClojureScript REPL, what the bootstrap script is for, and so on... and we certainly didn't come out with anything resembling a reasonable workflow.

But it seems like just hacking on the samples/hello folder with the "production settings" might be a good place to go from here if we actually wanted to start our own ClojureScript project. Who knows. One thing I promise though: if I ever figure any of this out, I'll come back and fix up the docs.

Post Script

Yes, I'm trolling. The problem of terrible intro docs is certainly not limited to ClojureScript: I witnessed a very smart coworker reduced to a quivering mess after spending the day trying to figure out JavaScript package managers. And naturally, he hasn't touched JavaScript since.

There are so many great projects out there, all looking to build up a loyal user base. Putting up barriers to entry is bad for the community and frustrating for new users. So please, fix your Getting Started docs!