Signature

Hue — a functional programming language for fun & play

May 14, 2012

Hue is one of my latest hobby projects that didn’t die after a week. It’s a functional programming language, in a sense. There are no statements in this language, but everything is an expression. An expression does something funky and returns something—hopefully—even funkier. That includes if..then..else as well as logical tests and functions.

Anyhow, this hobby language of mine is still very much in flux and I’ll probably change its syntax and behavior a few times before I’m really happy with it. Haskell, Erlang and Clojure all have some pretty cool features but I’ve never been friends with their syntaxes. Me wants something closer to Python. Me write language.

A programming language is in its essence a Human-Computer Interface. I’ve done these things in the past, for example the Move programming language. This time I wanted to write everything myself, starting at the instructions that the computer executes and all the way up to the runtime library, idioms, design opinions and concepts.

So far I’ve spent evenings and weekends during the last five weeks hacking on this, bust more so I’ve been reading conceptual stuff, like Joe Armstrong’s thesis paper “Making reliable distributed systems in the presence of software errors” (chapters 1 and 2), where Joe dissects the inherent problems with trying to model the real world using a non-1:1 mapping (e.g. imperative programming that fakes concurrency) and so forth.

From Hue to target assembly

A simple and completely useless program that contains a function which multiplies two integers with 9 and each other, then divides that with 4 and returns the result:

foo = ^(x, y Int) Int: z = x * y * 9
                       z / 4
a = 19
b = foo 4 (5*10*a)  # => 8550

Note a few things:

  • Whitespace is significant. Like in the Python programming language, a colon “:” character denotes that a block of expressions follow. When the line indentation level drops from whatever level the expression that owns the “:” character is at, the block is terminated. The foo function’s block contains two expressions.

  • Types are inferred. The language is strongly typed and in case the compiler is unable to infer the type, it will yield a compilation error. No types are inferred at runtime, which means that very few—or even no—errors related to types and value passing can happen when the program is run.

  • Functions are expressions and not a “special” thing. Functions can be passed around just like any other value.

  • Variables are actually just aliases and usually “folded” (removed and their values is just put in place) by the compiler.

Let’s compile this program:

hue hello.hue hello.ll

And look at the LLVM IR code that the Hue compiler generates:

define i64 @main() nounwind {                               # 1
  %foo_res = call i64 @"hello$foo"(i64 4, i64 950)          # 2
  ret i64 0                                                 # 3
}

define private i64 @"hello$foo"(i64 %x, i64 %y) nounwind {  # 4
  %multmp = mul i64 %x, %y                                  # 5
  %multmp1 = mul i64 %multmp, 9                             # 6
  %divtmp = sdiv i64 %multmp1, 4                            # 7
  ret i64 %divtmp                                           # 8
}

The Hue compiler generates LLVM intermediate representation code. Similar to what is output by e.g. Java and .NET compilers when an object file/program is built. LLVM is an amazing piece of compiler infrastructure software that enables a whole slew of features like native machine code generation, code optimization, etc. Going back to the above IR code, we see what actually happened to our program. I’ve given the lines above numbers, which we are referring to here:

  1. @main() is the entry point of our module. Or program in this case.

  2. We call the function hello$foo with two 64-bit integer values 4 and 5. We expect a return value that is a single 64-bit integer value, which we give the alias “%foo_res”. Notice how the a = 19 and (5*10*a) expressions where folded into 950 (“i64 950” in the IR above). Because values are constant, the compiler can “execute” obvious isolated parts of the program.

  3. Our module returns control, with the 64-bit integer value 0, to whatever called it (in this case, our program exists with status 0).

  4. This is where our function lives. “private” means that the function is only used inside this module, and “i64” means it returns a 64-bit integer value (Hue’s “Int” type is a 64-bit integer). The function takes two parameterized arguments which both are 64-bit integers and gives those parameters the aliases “%x” and “%y”.

  5. We ask the computer to multiply the two values behind the aliases “%x” and “%y” and give the resulting value an alias of “%multmp”.

  6. Again, we instruct the computer (these are so called “instructions”) to multiply two values: The result of multiplying “%x” and “%y”, which we did at line 5, with the number 9 and alias the result as “%multmp1”.

  7. We divide the “%multmp1” value with the number 4 and alias the result as “%divtmp”.

  8. We return the value behind “%divtmp” to the caller.

If we generate assembly for x86_64 (basically machine instructions), we get roughly the following:

  .section __TEXT,__text,regular,pure_instructions
  .globl  _main
  .align  4, 0x90
_main:                          ## 1
  pushq   %rax
  movl    $4, %edi              ## 2 (1/4) 
  movl    $950, %esi            ## 2 (1/4)
  callq   L_hello$foo           ## 2 (1/4)
  xorl    %eax, %eax            ## 3 (2/3)
  popq    %rdx                  ## 3 (3/3)
  ret                           ## 3 (4/3) ...
  .align  4, 0x90
L_hello$foo:
  imulq   %rsi, %rdi            
  leaq    (%rdi,%rdi,8), %rcx
  movq    %rcx, %rax
  sarq    $63, %rax
  shrq    $62, %rax
  addq    %rcx, %rax
  sarq    $2, %rax
  ret

Yeah, I know. This code gets scarier and scarier, but we can see how closely LLVM IR maps to target assembly, but we also understand the complexity of modeling something simple as the initial Hue program on x86_64 assembler.

We can run our program, which by the way doesn’t really do anything, either straight through LLVM as JIT-ed code using lli hello.ll or generate an object file and link it as a program:

llvm-as -o=- hello.ll | llvm-ld -native -o=hello -
./hello

Functional programming has for a long time been the toolbox of mathematicians and CS ninjas with beards (Johan and Erik — I’m lookin' at you). My guess is that math people—clever fellas—invented these things and created syntaxes that fell natural to them. I never really payed attention to math in school and have no math education beyond the very basics, like multiplication, yet I have come to realize the awesomeness of math and its concepts. So how about we take the awesomeness of functional programming—high modularity and code re-use, testability, stability, etc—to us programming peasants of Python, JavaScript, BASIC and Java? Perhaps this project will be an attempt on that, or perhaps not.

A performant immutable & persistent vector implementation

Besides rambling about some yet-another-hobby-language, I wanted to talk about this one awesome, concrete thing that has come out of this project: An immutable persistent vector inspired by and partly ported from Clojure’s PersistentVector. With this approach, you can freely manipulate a vector data structure concurrently without locking and more importantly without causing imperative situations where expected state is different depending on outside, out-of-our-control circumstances.

Impressive numbers: Starting with the empty vector and appending one single item at a time until we reach one million takes roughly 200ms on a single 3.4 GHz i7 core. That is an average of 200 nanoseconds per append operation. Keep in mind that an append operation effectively creates a new vector — this data structure is in fact immutable, so we have to create a new, derived structure every time we “modify” it. With a traditional array-style structure, where we have N items in a uniform sequence, is cheap to copy when N is reasonably small (like 100 or so), but becomes a real bottleneck (and a problem for concurrent operations) when N grows.

Now, writing to and updating vectors are usually less common that accessing items in them. Pretty convenient then that this implementation offers almost-constant time random access. Technically is a little less than constant, but it’s negligible in my opinion (see comments in Vector.h for more info).

The source for this implementation is available from the Hue GitHub repository together with some unit tests (look in the “test” directory or run the “test” make target).

Numbers from running make clean test_vector_perf:

  • N = 100 (this run takes the unfortunate initial impact of lazy-loaded symbols)
    • Inserting 100 values: 0.028 ms (avg 280 ns/insert)
    • Accessing all 100 values: 0.002 ms (avg 20 ns/access)
  • N = 100 000
    • Inserting 100000 values: 20.722 ms (avg 207.22 ns/insert)
    • Accessing all 100000 values: 0.531 ms (avg 5.31 ns/access)
  • N = 1 000 000
    • Inserting 1000000 values: 204.391 ms (avg 204.391 ns/insert)
    • Accessing all 1000000 values: 5.171 ms (avg 5.171 ns/access)
  • N = 10 000 000
    • Inserting 10000000 values: 2002.78 ms (avg 200.278 ns/insert)
    • Accessing all 10000000 values: 59.592 ms (avg 5.9592 ns/access)
  • N = 100 000 000
    • Inserting 100000000 values: 19741.9 ms (avg 197.419 ns/insert)
    • Accessing all 100000000 values: 674.349 ms (avg 6.74349 ns/access)

We can reason that for N up to at least 100 million, both insertion and random access is close to constant time complexity. It’s not nearly as fast as a traditional mutable vector which grows uniform regions of memory (e.g. std::vector or a plain C array), but given it’s immutable property, this is very good.

Source code and other goodies are available at github.com/rsms/hue.

PeerTalk — hug it out over USB

Mar 31, 2012

PeerTalk is a small iOS and OS X Cocoa library for communicating over USB and TCP.

There are at least three upsides to connecting over USB:

  1. Secure. Only the apps in each end of the USB cable can communicate with each other.

  2. Simple. No entering hostnames, ports and browsing openly announced internet services.

  3. Low latency.

This little thing is something I hacked together for fun and I haven’t spent more than a few days, so there will be bugs. It’s released under an MIT license, thus you can use this for both fun and profit.

https://github.com/rsms/peertalk

Working with WebKit as a UI compositing engine

Oct 16, 2011

UILayer

UILayer provides a JavaScript API on top of WebKit for working with the concept of layers. Instead of manipulating DOM elements using a myriad of mixed concepts, you go though a single, well defined API.

If you’re running a WebKit browser (Chrome, Safari, iPhone, iPad, etc), have a go with one of these:

Read more at rsms.me/uilayer →

February 24, 1955 – October 5, 2011

Oct 05, 2011

Here’s to the crazy ones

The misfits. The rebels. The troublemakers. The round pegs in the square holes.

The ones who see things differently. They’re not fond of rules. And they have no respect for the status quo. You can quote them, disagree with them, glorify or vilify them.

About the only thing you can’t do is ignore them. Because they change things. They invent. They imagine. They heal. They explore. They create. They inspire. They push the human race forward.

Maybe they have to be crazy.

How else can you stare at an empty canvas and see a work of art? Or sit in silence and hear a song that’s never been written? Or gaze at a red planet and see a laboratory on wheels?

We make tools for these kinds of people.

While some see them as the crazy ones, we see genius. Because the people who are crazy enough to think they can change the world, are the ones who do.

Steve, you’ve been a great inspiration and changed so many lives to the better. Your legacy will live on.

Designing a modern web-based application — Dropular.net

Sep 10, 2011

One and a half years ago me and Andreas released a new version of dropular.net — a new kind of web app that runs completely in the browser. Today, this approach to designing web-based applications running client-side has become popular, so I thought I’d share some of the issues, approaches and design choices made during the development of Dropular.

I designed Dropular just as I would design a desktop application — the UI and related logic runs on the host computer (client). The host knows how to present a GUI and the host knows about user input, end-user’s environment state and so on, making UI code running on the client-side the natural choice. Then again, there’s always data. Dropular.net communicates with one or more backend access points to read and write data, verify authentication and so on.

Basically, we serve only data from the access point and run almost all code in the client web browser:

Figure 1

When a client visits dropular.net, three files are sent as the response: index.html, index.css and index.js — view, layout and logic, respectively.

If you view the source of any of these files you might notice that the code looks suspiciously computer generated. That’s because it is computer generated. As part of Dropular, I wrote a web-app client-server kit dubbed oui which given a source tree compiles and produces a runnable index.html file (together with an index.js and index.css file).

Oui provides a CommonJS module interface and groups together LESS/CSS, JS and HTML into logical modules which are name-spaced.

Demo and source code

First, let’s have a look at the actual product and experience (since it’s invite-only). This is a screen cast of me using the current, live website:

Now, here’s a redacted snapshot of the Dropular source code: https://github.com/rsms/dropular-2010. Note that this code depends on oui and a few other open source projects.

Authentication

authIn a model where the logic lives in the client, security is a different nut to crack. You need to deal with automatic re-authentication, network reconnection, server fade-over, etc.

Authentication is performed in a two-step process, allowing an intermediate representation to be cached in the client, enabling automatic fail-over to other access points and automatic login when later visiting the site.

Figure 2

It goes a little something like this:

[Step 1] Client sends a request for challenge:

← GET /session/sign-in?username=John

[Step 2] The server:

  1. Verifies and fetches information about the user related to username
  2. Generates a UUID that is uses as a session ID
  3. Creates a temporary session object in memory, associated with that session ID
  4. Generates a nonce using: BASE16( SHA1_HMAC( server_secret, timestamp ":" random_data ) )
  5. Puts the nonce in the user’s session and registers a hook to clear the NONCE upon next request containing the associated session ID.
  6. Responds to the client with the nonce and the user’s canonical username:
→ 200 OK {"nonce":<nonce>, "sid":<session_id>, "username":"john"}

[Step 3] The client:

  1. Stores the session_id locally, to be used for future requests
  2. Displays a user interface where the user inputs her username and password
  3. Calculates the passhash: BASE16( SHA1( username ":" password ) )
  4. Calculates the auth_response: BASE16( SHA1_HMAC( auth_nonce, passhash ) )
  5. Sends another request, this time with a payload, to the server:
← POST /session/sign-in {"sid":<session_id>, "username":"john", "auth_response":<auth_response>}

[Step 4] The server:

  1. Calculates an auth_token: timestamp ":" BASE62( SHA1_HMAC( passhash, server_secret ":" timestamp ) )
  2. Saves the auth_token in the user’s session object
  3. Verifies the auth_response sent by the client: BASE16( SHA1_HMAC( nonce, passhash ) ) == auth_response
  4. Deletes the nonce from the user’s session
  5. Responds with the auth_token and a complete description of the user (name, email… things like that):
→ 200 OK {"auth_token":"xyz", "sid":"xyz", "user":{<user details>}}

The client stores the auth_token locally, to be used for future automatic re-authentication.

Later in time, when the client sends whatever request to the server and includes its session_id, the server will evaluate the following logic:

if session = Session.get(session_id):
  if session.auth_token:
    allow_request()
  else:
    perform [Step 4]
else:
  session = Session.new()
  → 401 {"sid":session.id}
  perform [Step 3], starting at point 4, and finally re-send original request (client)

Since [Step 3], point 4 and forward does not require user input, re-authentication—and thus backend fade-over—can be done completely in the background. The user experience will the that the original request (e.g. a click on a button to show some content) takes a little longer time than it usually would.

User interface

LayoutSince the user interface is created, rendered and maintained solely by the client (i.e. web browser), there needs to be some structure. The HTML DOM is actually a great view representation and in combination with CSS gives you control of each pixel on the screen, and at the same provides a nice separation between view structure and layout. However, these kinds of websites tend to have many different “screens”, or view states if you will, quickly making your regular HTML and CSS code a freaking mess.

What we did was to have a mind set as if we where writing a desktop application — we define logical components in folders and files that reflect the structure of these components. We then process, or compile, these sources into machine-and-network optimized code (HTML, CSS & JavaScript), just like you do with “regular” software development.

A nice side-effect of having an intermediate “compile” step is that you can write your source code in whatever language suits you and your project — your no longer limited to the languages and coding styles dictated by web browsers. For instance, you can define your layout code in LESS instead of CSS and write your logic in Move instead of JavaScript.

Downsides to a “compiling” approach

This approach obviously has some downsides, one of them relatively painful: debugging. Since the code you’re running does not directly reflect the source files you have in your structure of logical modules, finding and fixing a problem becomes harder as you need to back-track and search your source for certain things. In the end, we took a pragmatic approach to this and simply generated human-readable code that’s annotated with the path names of the source.

Templates in the DOM

For views that aren’t permanent (most views aren’t) we are using HTML templates, kept inside the DOM as data-only node trees:

<module id="drops-drop">
  <drop>
    <h1></h1>
    <img>
      ...
  </drop>
</module>

With CSS making any module node tree a data node tree, exempt from layout and display:

module { display:none; }

Some module logic (e.g. JavaScript code) then clone appropriate parts of its template, which is made available to a module using the __html convenience variable:

// Register a hook for a certain URL
oui.anchor.on(/^drops\/(<id>[a-zA-Z0-9]{25,30})/, function(params, path, prevPath) {
  // Load data for drop with <id>
  oui.app.session.get('drops/drop/'+params.id, params, function(err, drop) {
    // Make a new instance of the <drop> child node tree of our HTML template:
    var view = __html('drop');
    // Configure the view
    view.find('h1').text(drop.title || drop.origin);
    ...
    // Finally add the view to an active part of the DOM
    mainView.setView(view);
  });
});

Data storage and the problem of many-to-many

dataSince we have a very clean separation of data and presentation, CouchDB made a lot of sense to us. In CouchDB, data is represented by logical structured blobs called “documents” — basically it’s a key-to-JSON store.

Dropular.net has a feature where you can follow any number of other users and look at a feed of images created by all those users. In data terms, this is a many-to-many relationship which when using a RDBMS like MySQL is expensive (computational wise). With CouchDB on the other hand, many-to-many relationships are very easy to define and they are cheap to maintain!

Basically, we lazily define a CouchDB view per user _design/user-drops-USERNAME/_view/from-following with the following map function:

function (doc) {
  var following = %FOLLOWING;
  var user, createdBy, created; // find lowest timestamp
  for (user in doc.users) {
    var t = doc.users[user][0];
    if (!created || t < created) {
       created = t;
       createdBy = user;
    }
  }
  for (user in doc.users) {
    for (i=following.length; --i > -1;) {
      if (following[i] === user)
        emit([created, user], doc._id);
    }
  }
}

Example: GET http://dropular.net/api/users/rsms/following/drops

{ "drops": [
    { "id": "9uQyA5tTraIkiVHG5l1XdPRHwfg", "key": [1274772176060,"suprb"] },
    { "id": "cytCrjVJPQOCXiSqF1MV6GqPEt1", "key": [1273706969465,"suprb"] },
    ...
  ],
  "total": 2701,  "offset": 0
}

Now, CouchDB will make sure to run this function every time any related document is modified, added or removed, effectively keeping all relevant “from-following” indexes up-to-date. CouchDB is very good at these incremental updates, so even though this looks complex and slow, this function is compiled to an internal representation and only run on the modified values, not the complete data set, making an update both atomic and complete within a few milliseconds.

As part of Dropular, I wrote a Node.js module for dealing with CouchDB that has a very low level of abstraction: https://github.com/rsms/node-couchdb-min.

Access points aka The Server

As any app that centralizes data, authentication, etc, you need something to serve as the hub. We call these access points, as they are the contact surface between the client application and whatever lives in the central backend (CouchDB, AWS services, etc). Since I’ve been involved in Node.js for a long time, Node.js was a given choice. Actually, this was such a successful solution that we sustained over 1000 API requests/second on one single small AWS EC2 instance with less than 1.0 in load (during our initial release which caused a thundering heard-like wave of visitors). Even for a commercial website, that number is considered good.

Scalability as an effect

The Oui app kit supports virtually an infinite number of access points to be used, making this approach of running all the logic in the client an extremely scalable solution.

Figure 3

— Just add as many access points as you need, effectively scaling close-to linearly (at least as close to linear as your backend dependencies allow).

A model which relies on persistent sessions or rendering of the user interface in a central location (i.e. on the server) can never reach this level of scalability-to-price/complexity ratio.

Today & tomorrow

Today, 21 months later, the current browser technology allows for even more sophisticated client-and-access-point solutions, where everything from complex image processing (canvas 2D and 3D) to data processing (WebWorkers) can be done client-side. DOM manipulation is much cheaper, JavaScript runs much faster and OAuth 2.0 is an easy-to-use (in contrary to 1.0), suitable authentication schema for these kinds of approaches. 3D-transforms for hardware accelerated, high-performance 2D and 3D user interface effects as well as host-native, fluent animations defined in simple CSS.

I’m really curious to see what’s next — the web is rapidly transforming from a “hacky” document presentation technology to a rich application development and distribution platform with standards that make sense. No more live hacking on FTP servers or behemoth HTML-generating Java servers.

An update on the programming language Move

Jul 30, 2011

A few months back I wrote a programming language called Move. Before the advent of Move, JavaScript (on Node.js) was my universal language of choice. Two years earlier it was Python. During the last four months I have basically been exclusive with Move — quick hacks, data mangling scripts, network services, websites, iphone apps… you name it. What initially was a fun week of language research and interviews with people, turned into a very usable programming language and library.

Today Move has evolved — from what was first released on March 2, 2011 — over nine releases, making the language even simpler and listening to user feedback.

The web is the future

It’s inevitable. The web (well, stuff over HTTP viewed in a web browser) is the app platform of tomorrow. Move provides a normalized environment, a uniform library with a standard CommonJS module system. This is actually a huge deal since what traditionally incurred the feeling that JavaScript was a second-class programming environment, should be hugely contributed to the vast number of bugs, API differences and library discrepancies implied by the web browser landscape. Although the API of today’s web browsers are generally coherent, there are still a bunch of differences your everyday JavaScript web browser engineer need to — painfully — be aware of and feature-test for.

For example, a common thing to do is to iterate over items in a list:

someArray.forEach ^(item, i) {
  print i+':', item
}
someObject.forEach ^(key, value) {
  print key+':', value
}

On modern browsers, that code will be very fast as it’s implemented natively.

In JavaScript, you would need to do some feature testing…

var i, key, apply = function (item, i) {
  console.log(i+':', item);
};
if (typeof Array.prototype.forEach === 'function') {
  someArray.forEach(apply);
} else {
  for (i = 0; i < someArray.length; ++i)
    apply.call(someArray, someArray[i], i);
}
var HOP;
if (typeof Object.prototype.hasOwnProperty === 'function') {
  HOP = Object.prototype.hasOwnProperty;
} else {
  HOP = function (name) { return this[name] !== undefined; };
}
apply = function (key, value) {
  console.log(key+':', value);
};
for (key in someObject) {
  if (HOP.call(someObject, key))
    apply.call(someObject, key, someObject[value]);
}

I would chose the Move way any day of the week.

“But I’ll just use jQuery” you say and wonder if this normalization thingy in Move is just yet another library. No. Move provides a ES5 environment, equivalent to a modern version of Chrome or Safari. As time progress, the ES5 standard will be completely implemented on all platforms. When that happens you no longer need a 3rd party library (theoretically speaking). You’re investing in learning the future standard instead of the API of a 3rd party compatibility library.

Note that some features of ES5 requires compiler, vm or otherwise host-level support in older browsers, which is thus impossible to “glue together”. On the topic, Annotated ECMAScript 5 is a great and accessible documentation of the ES5 standard.

Another pretty awesome feature of Move is that you get a standard CommonJS module system. That basically means that slicing up your code into modules is easy peacy:

import foo, bar
x = foo.someFunction()
y = bar x
export z = y * x

Part of the Move language are the two keywords import and export. Import is a convenience preprocessor for the CommonJS require function.

import foo

Compiles to:

foo = require 'foo'

The export keyword similarly converts a statement like:

export foo = 5

To:

exports.foo = foo = 5

The exports variable is part of the CommonJS module specification and represents the API that your module (source file) provides (exports) to other source code.

It’s completely optional to use these convenience keywords.

Here’s a more complete example of modules in a web browser environment:

<script src="http://movelang.org/move.js"></script>
<script type="text/move" module="bar">
import foo, capitalize
export sayHello = ^(name) {
  print foo.makeHello capitalize name
}
</script>
<script type="text/move" src="capitalize.mv"></script>
<script type="text/move" module="foo">
export makeHello = ^(name) { 'Hello '+name+'!' }
</script>
<script type="text/move">
import bar
bar.sayHello 'worlds'
</script>

Slicing and dicing collections

Move falls into the category of “end-user data” programming languages (I just made that up), thus dealing with text and lists of items is a very common task. Move provides a slice syntax which should come natural to e.g. Python programmers:

print "hello"[1:3]  # "el"

x = [1,2,3,4]
print x[1:3]        # [2, 3]
x[1:3] = 9
print x             # [1, 9, 4]
x[1:] = [9, 10]
print x             # [1, 9, 10]

Since Move is heavily based around the core concept of first-class functions, this slice syntax compiles to simple function calls:

foo[1:3]
foo[1:3] = 9
foo[1:] = 9

Which is equivalent to:

foo.slice 1, 3
foo._move_setSlice 1, 3, 9
foo._move_setSlice 1, undefined, 9

This means that any object can support slices by simply implementing both or one of slice(startIndex, endIndex) → list (getter) and _move_setSlice(startIndex, endIndex, value) → list.

Embedded HTML and compiler preprocessor API

This is a pretty awesome feature: HTML literals.

url = "http://movelang.org/res/logo.png"
img = <img src="{url}"/>
img.width = 500
document.body.appendChild img

With this feature comes the ability to plug in preprocessors to the Move compiler. Embedded HTML (or EHTML for short) is currently the only plugin that ships with Move, but the preprocessor API is pretty simple: Create a module which exports a process function process(string moveSource, object compilerOptions) → string moveSource:

export process = ^(source, options) {
  # Transform source
  source
}

Then the preprocessor need to be registered with the compiler:

move.preprocessors['my-preprocessor'] = process

Finally, specifying the preprocessor when compiling:

move.compile {source:source, preprocess:['ehtml', 'my-preprocessor']}

The order of which preprocessors are specified in the “preprocess” argument to move.compile decides which is applied first. By default Move will enable the “ehtml” (Embedded HTML) preprocessor by default when run in a en environment that provides a DOM (i.e. a web browser).

Classes — Object factories with prototype chains

Since the birth of Move “class definition” has been a common feature request: Ability to define prefab prototype chains.

Move leans toward the “good parts of JavaScript”, thus the “new” keyword (added to JavaScript simply to make it look like Java — oh politics) should be avoided. Object.create is the recommended way of creating new objects based on custom prototypes. Still, Object.create is limited to creation (which is a good thing). From the eyes of Object.create, there’s no notion of constructor, or rather; there’s no difference between a constructor function or any other function.

As Douglas Crockford states it:

JavaScript is a prototypal language, but it has a new operator that tries to make it look sort of like a classical language. That tends to confuse programmers, leading to some problematic programming patterns.

Avoid the “new” keyword and use literals or factory functions instead.

Say hello to Move’s class construction function:

Animal = class {
  age: 1,
  toString: ^{ "I'm a "+@kind }
}

elephant = Animal {kind:"slow and kind fella"}
print Text elephant  # "I'm a slow and kind fella"
print elephant.age   # 1

In the above case we define the factory Animal, having a prototype with two values: age and toString. The Animal factory produce objects with a prototype of Animal.prototype.

We can create another factory which prototype inherit from the Animal prototype:

Cat = class Animal, {
  constructor: ^(name, age) {
    @kind = "furry little creature"
    name && (@name = name)
    age && (@age = age)
  },
  toString: ^{
    s = Animal.prototype.toString.call this
    s + " named " + @name
  }
}

cat = Cat {name:"Busta", age:10}
print Text cat  # "I'm a furry little creature named Busta"
print cat.age   # 10

Note that we defined a constructor function on the prototype. In this case, calls to the factory will invoke that function (instead of the implicit and generic create function).

Constructor functions (or you could think of them as initialization functions) need not be defined on subclasses in order to invoke a superclass’s constructor:

Zelda = class Cat, {
  name: "Zelda",
  toString: ^{ "I'm awesome and my name is "+@name }
}

Since the above Zelda prototype does not define a constructor, the parent prototype’s constructor will be called (that is, Cat.prototype.constructor) when the Zelda factory is invoked

zelda = Zelda {age:5}
print Text zelda  # "I'm awesome and my name is Zelda"
print zelda.age   # 5

As usual with Move, class is simply a runtime function (__move.runtime.__class).

Actually, the Zelda factory and prototype chain can be described (and traversed) like this:

Zelda                                # [function]
Zelda.prototype                      # { name:"Zelda", toString:[function] }
Zelda.prototype.prototype            # -> Cat.prototype
            Cat.prototype            # { constructor:[function], toString:[function] }
            Cat.prototype.prototype  # -> Animal.prototype
                   Animal.prototype  # { age:1, toString:[function] }
                   Animal.prototype.prototype  # Object.prototype

Helpful command line interface

The move CLI tool (a program with a text interface) acts both as an operating system entry-point for Move programs run directly on a system and as a utility for dealing with and processing Move code.

Run a Move program:

move foo.mv
move run foo.mv

Run Move code from stdin:

echo 'print "hello"' | move run
move run < foo.mv

Output the parser’s Abstract Syntax Tree that represents your code, as JSON:

move compile --ast foo.mv

Show the JavaScript generated by the compiler:

move compile foo.mv

Show the list of global options and available commands:

move -h
move --help

Show documentation for a specific command (“compile” in this example):

move help compile

Create a stand-alone web-browser compatible JavaScript file from one or more source files:

move compile --bundle-standalone foo.mv bar.mv leet.js
move compile --bundle-standalone --basedir lib lib/*.{mv,js}
move compile --bundle-standalone --basedir lib --output bundle.js lib/*.{mv,js}

This article and examples in it assumes the latest release of Move at the time of publishing this (0.4.2).

More information on Move can be found at movelang.org

Air Shaffer

Jun 25, 2011

Went flying with Shaffer and Lee this Friday evening, starting at Palo Alto, flying up over SFO, through San Francisco, over Oakland and finally back to Palo Alto.

3 months at Facebook

Jun 15, 2011

I’ve now been at Facebook in Palo Alto, California for almost three months. And I love it.

This little textual outlet of mine has been silent for a while, mainly because I’ve been so caught up in a very exciting thing we’re making at Facebook, and probably will continue to be for a while.

Me in the Facebook HQ backyard

What really blows my mind about this place is how small it feels, yet we are thousands of people working at Facebook. The organizational structure is very flat and most responsibility is distributed, which is a very interesting concept. I work as a product designer—in our small but amazing Product team—meaning I do everything from conceptual development and management, to interaction design and graphic design.

Chris, Brandon, Francis and Joey

We generally have one product designer and one product manager pair up to form a “mini product team” in each project. This gives me the feeling close to that of a small start-up — “let’s do this together!”.

At the end of this year we will be moving into our own little town — a new totally awesome campus in Menlo Park — which is currently in it’s last stages of construction.

You can find a couple of images from my first two months in “My first two months”…

Moving to San Francisco

Moving to San Francisco, California from Stockholm, Sweden is a whole different story.

San Francisco seen from Twin Peaks

First off, this is a totally amazing place, full of life.

There’s tons of paperwork that is obscure, boring and tricky. For instance, while in the USA, no one will tell you that you need to file an AR-11 “Change of Address” form within 10 days, or you are breaking federal law and might get kicked out of the country. Or file for an SSN using old physical paper and pen which is then manually handled and processed by a bunch of humans.

Yes, most things here in the USA is still on physical paper, traveling in physical envelopes, just to be scanned or re-entered into a computer again, by a human.

Compared to Sweden, I’d say the infrastructure of California is about 25 years behind. Checks are still heavily used, banks are immature, etc. Being in San Francisco, you’re lucky if you get 500kbit/s over 3G — if you can even get stable enough connection. 4G here is more a myth than something that actually exists (I have a 4G modem and have yet to find a connection after 2 months of use). In Stockholm, you basically never go below 1Mbit/s over 3G and connections are very stable.

Then we have basic infrastructure, like cars, public transportation, landline connectivity, etc. Everything barely working. For instance, public transportation buses are old and technically inefficient with their giant tires and old diesel engines, spewing out black smoke. Busses like that would never even pass the minimum environment requirements in Sweden. Even the Stanford University runs buses like these.

But all that stuff is just an itch — people here are amazing!

I happily trade this lack of modern infrastructure for the brilliant openness and warmth of these people.

Highway 1 road trip makes us jumpsy

Now, back to changing the world.

Spotify box by Jordi Parra

Mar 24, 2011

Fellow designer Jordi Parra recently finished his masters degree project “Spotify box” — a beautiful little radio-like device which plays music through the Spotify platform. What’s really neat about Jordi’s Spotify box—except from its gorgeous design—is that it brings back the physical interaction with music as an object, but adjusted to the 21st century. A playable item is represented by a small token, conveying a link by wireless RFID technology.

See for yourselves:

Some more pictures of the Spotify box, grabbed from Jordi’s work log:

My take on Firefox 4

Mar 23, 2011

In the fast-paced world of web browsers Mozilla Firefox owns the second largest market share. Yesterday the much anticipated version 4 of Firefox was released and these are my reflections. I’ll mostly be comparing Firefox 4 to Google Chrome 11 on Mac OS X, since that’s what I use day-to-day.

Firefox 4

Startup time and general UI responsiveness

Firefox has traditionally been the “slow one” on Mac OS, mainly due to heavy disk I/O and CPU usage as an effect of the XUL technology and other tech details, like the absence of a font cache in earlier versions. Firefox 4 feels much more responsive than Firefox 3.6 (the previous version), but is still relatively slow to start when compared to Safari or Chrome, both which are native applications that don’t need to parse a ton of XML when they start (like Firefox does).

This is a minor issue and somewhat subjective.

Windows & tabs

As with most modern browsers, multitasking in Firefox is based around a tabbed user interface. The window of Firefox 4 looks like this:

Screen shot 2011 03 23 at 16x

Like Chrome, tabs have a maximum width and will uniformly shrink (horizontally) when more room is needed for new tabs. However, the window header feels rather large and a bit clumsy. Compared to Chrome, it’s actually just a few pixels higher, but the tabs in Firefox are smaller and the window contains the current tab’s title.

Since most people using these web browsers use a mouse or trackpad to navigate tabs, having small tabs (and thus hit areas) is a bad idea since the user will have a harder time hitting the right tab. Mozilla (the creators of Firefox) probably decided to make a compromise on the size of the tabs in order to fit a title into the window header, something that Chrome lacks.

I personally don’t believe in long and descriptive window (or page) titles in this context. They tend to be a mere repetition of a (in most cases) better and richer title displayed in the actual website. I would rather see that Firefox went down the same lane as Chrome and Internet Explorer 9 and skipped the window title. Something like this:

Alternative without window title

Update: Abhijit Shylanath pointed out that removing the title bar is possible in the Microsoft Windows version of Firefox 4.

Some details related to window UX where Firefox 4 got it right but Chrome fails:

Closing tabs

A really nice feature in Chrome is how you can quickly close a bunch of tabs because of how tabs align. Basil Safwat has a good write-up about this. I expected Firefox 4 to sport the same nifty UX after reading “Making tab closing as easy as click, click, click”. But no.

Closing multiple tabs

Mozilla are already on to this which appears to get fixed til the next release. (Thanks to Erik Möller for the tip).

Switching tabs

A really neat feature, new in Firefox 4, is the ability to switch to already open tabs by simply typing in (partially matching) text or url into the location bar.

Update: There’s an experimental feature in Google Chrome 11 (and newer) which can be enabled to provide similar functionality. Visit about:flags and enable “Focus existing tab on open”.

Developer’s console

The interactive console primarily used during website development is called “Web Console” in Firefox 4 and — unlike Chrome, Safari and previous versions of Firefox — it appears on the top of the window rather than at the bottom. Albeit still in a split-screen pane.

Web Console in Firefox 4

The position of the console is probably mostly a matter of taste. However, this “Web Console” is much simpler than the one found in Safari and Chrome as it only provides an interactive JavaScript console and event log. The console found in WebKit browsers features a broad set of different kinds of developer tools, including script debugger, network monitor, DOM inspector, etc. These features can however be added to Firefox by installing various extensions.

A big downside with the “Web Console” in Firefox 4 is that it dramatically slows down the loading of any website (feels like a factor of 5).

System integration

Any modern computer system (i.e. operating system, applications and settings) is a carefully balanced circus act. You have color calibration, text input, language dictionaries, UI behavior, etc. — all shared between applications to provide an intuitive, low-barrier and powerful user experience.

Poor system integrationUnfortunately due to how Firefox is built (it’s like it has its own little operating system which runs the actual app), system integration is relatively poor.

For instance, Firefox is unable to use the user’s spelling dictionary. If I open up an application (for instance TextMate or Pages), write some text and the spell checker finds a word it doesn’t recognize, e.g. my name “Rasmus”, I can tell it that “This is a correctly spelled word, please learn it” and all other applications will later know how “Rasmus” is spelled. Except for Firefox which uses its entirely own spelling system. This means that, like in the screenshot to the left, you will need to teach the Firefox spell-checker and fill the Firefox spelling dictionary from scratch.

This is how the user’s spelling dictionary (shared among all apps, but not supported by Firefox) works:

OS X user spelling dictionary

Although Firefox 4 fails horribly on integrating with the shared spelling system, it does get it right with word dictionary lookups (Ctrl+Cmd+D by default), correctly showing the dictionary word-pop-over. Chrome does not show this pop-over, but instead launches the Dictionary application, relieving Chrome itself from user input focus (a bad thing). Update: This will likely be fixed in Chrome 12 (thanks to Christopher Berlusconi Quackenbush for the tip).

Another relatively irritating lack of system integration is dragging stuff from Firefox to e.g. the desktop. When you drop something it will not appear where you dropped it, but rather added to the default location (somewhere on the rightmost part of your desktop). I tend to use my desktop as a landscape of semi-temporary piles of documents, visually grouped. Using Firefox, I must re-position the file each time after I’ve dropped it on the desktop. Tedious and definitely unnecessary.

File selection/opening

An excellent and very useful feature in both Chrome and Safari is the ability to drop a file onto a <input type="file"> input control:

Dropping files in Chrome

Unfortunately, this is not possible in Firefox 4. In fact, if you try to drop a file on a file control, Firefox will replace the whole website by browsing to the file you dropped, effectively causing any unsaved data to vanish into the void of interwebs (i.e. text typed into a form).

Also, Firefox uses a new window when browsing for files rather than the OS X standard “sheet” display (according to the Apple HIG and Apple’s own products). Here we see Google Chrome (left) displaying a standard OS “open file sheet” and Firefox (right) opening a new window (with a mysterious “Hide extensions” checkbox which did nothing when I checked it):

File browser dialogs

The problem with displaying a new window is

  • There’s no apparent attachment/link between a web page’s window which requests your attention to select a file.

  • The position of the “open file” window is not visually synchronized with the calling web page’s window, thus leading to a higher cognitive load for the user.

Miscellaneous

When quitting (terminating) Firefox, the state of tabs and open windows is saved, but when later starting Firefox the previous state is not restored. To restore a previous state, you have to manually select “History” → “Restore Previous Session” in the main menu. Edit: This is possible by setting “Preferences” → “General” → “When Firefox starts” to “Show my windows and tabs from last time”. I much prefer how Chrome does this — automatically restore any saved state at launch. This makes restarting Chrome (when restarting the computer or upgrading Chrome) and later resume your work less of a pain.

When dragging around tabs you don’t see what you are dragging. Instead, an image representing part of the contents of the tab is used for the “drag image”. There’s also no feedback (except from a tiny blue “insertion arrow”) when moving a tab to a different position in the same window. Both Chrome and Safari follow OS standards and display a visual replica of the object you are moving — a full tab with all its GUI parts. When moving a tab around you also get instant feedback as other tabs rearrange themselves, backed by an aiding animation, to give you a hint of where you are about to place your tab.

Now what?

Although Firefox 4 is a clear improvement over the previous version, it’s not the ultimate sports car you’ve been dreaming about taking to the streets. If you are hooked on some of the many extensions available for Firefox which does not exist for Chrome, stick with Firefox. Otherwise I recommend you go with Google Chrome.

Comments