Friday, January 22, 2016

My blog has moved

My new blog can be found at isiahmeadows.com/blog.html. This will be the last post in this location, and you can expect to find all future blog posts there, as well as all of my past blog posts (except this one).

For the few of you that have been watching my blog so far, I'm glad you spent the time reading it, and I look forward to seeing you all there. :-)

Tuesday, September 29, 2015

Tape === awesome

tape is awesome. Nobody likes writing thousands and thousands of lines of unit tests, but I'd have to say that tape makes it easy. It takes a lot less time and code to write the tests. Compare these two assertions in Mocha and tape:

(I'll shamelessly admit I yanked many of these from Mocha's website.)

// Mocha
var assert = require("assert")
describe('Array', () => {
  describe('#indexOf()', () => {
    it('returns -1 when the value is not present', () => {
      assert.equal(-1, [1,2,3].indexOf(5))
    })

    it('returns the index when the value is present', () => {
      assert.equal(2, [1,2,3].indexOf(3))
    })
  })
})

// tape
var t = require('tape')
t.test('Array', t => {
  t.test('#indexOf()', t => {
    t.equal(-1, [1,2,3].indexOf(5), 'returns -1 when the value is not present')
    t.equal(2, [1,2,3].indexOf(3), 'returns the index when the value is present')
  })
})

Also, if you're dealing with asynchronous code, it's just as easy.


// Mocha
describe('User', () => {
  describe('#save()', () => {
    it('saves without error', done => {
      var user = new User('Luna')
      user.save(done)
    })
  })
})

// tape
var t = require('tape')
t.test('User', t => {
  t.test('#save()', t => {
    t.test('saves without error', t => {
      t.plan(1)
      var user = new User('Luna')
      user.save(err => t.end(err))
    })
  })
})

The beauty of all of this is that it's so simple. You also don't have any global pollution. The tape tests can be run with node test.js. The tape command line runner does this very thing; it just runs the directory recursively when given one. And as for pretty output, there's a lot of tools out there that only need piped into. If you like the output of a C program that accepts it from stdin, you can use that reporter as well. No opinions needed.

And that's why I like tape. Tests made simple.

Monday, July 27, 2015

Objects linked to other objects - Simplifies so much

I recently made my first npm module (babel-plugin-proto-to-create), but this just stems from my general frustration with class-based OO. Not saying it's a terrible thing at all, or that I can't understand it at all, but there's nothing simpler than objects linked to other objects. Nothing more elegant than this:


const Vehicle = {
  new(make, model) {
    return {
      __proto__: this,
      make, model,
    }
  },

  toString() {
    return [
      "Type:  " + this.type,
      "Make:  " + this.make,
      "Model: " + this.model,
    ].join("\n")
  },
}

const Car = {
  __proto__: Vehicle,

  type: "Car",
}

const Truck = {
  __proto__: Vehicle,

  type: "Truck",
}

Merely creating an instance is as simple as this:


let car = Car.new("Nissan", "Ultima")

I really love the simplicity of this, pure prototypal OO. It's simple, concise, and beautiful. Or, if you'd prefer, you could always use ES6 classes:



class Vehicle {
  constructor(make, model) {
    this.make = make
    this.model = model
  }

  toString() {
    return [
      "Type:  " + this.type,
      "Make:  " + this.make,
      "Model: " + this.model,
    ].join("\n")
  }
}

class Car extends Vehicle {
  constructor(...args) {
    super(...args)
    this.type = "Car"
  }
}


class Truck extends Vehicle {
  constructor(...args) {
    super(...args)
    this.type = "Truch"
  }
}

Lot more boilerplate. Extending mixins in ES6 classes are also a little more complicated:


function mixin(Class, ...srcs) {
  class C extends Class {}
  Object.assign(C.prototype, ...srcs)
  return C
}

class Foo extends mixin(Bar, Baz) {}

// Or, if you want to mixin classes...

function mixin(Class, ...others) {
  class C extends Class {}
  Object.assign(C.prototype, ...others.map(D => D.prototype))
  return C
}

class Foo extends mixin(Bar, Baz) {}

Why do classes, even JS prototypal-based classes, have to be so complicated?



function mixin(Type, ...others) {
  return Object.assign({__proto__: Type}, ...others)
}

const Foo = {
  __proto__: mixin(Bar, Baz),
}

And with ES7's object spread, the mixin picture is only going to make this nicer:


const Type = {
  __proto__: Foo,
  ...Mixin1,
  ...Mixin2,

  method() {},
}

Very lightweight mixins that don't need any syntactical support. Not to mention you could even define these is-a/has-a relationships conditionally at object creation time:


const Type = {
  new(condition) {
    return {
      __proto__: this,
      ...(condition ? Mixin1 : Mixin2),
    }
  }
}

I know of no other language with this kind of flexibility.

Sunday, November 9, 2014

ES6 is functional, imperative, and OO

Yes, I know that, lately, there has been a fad about functional programming. Examples include C++ and Python getting lambdas, people envying those with Haskell/OCaml/etc. experience, and so on. But, in my experience, JavaScript has always been in the grey area. It's been called functional, imperative, "Lisp in C's clothing", object oriented, and so many other things. Yet, none of these actually describe the language, which is, in reality, a mixture of all these things.

Now, here's why I believe ES6 to be functional, imperative, and object oriented, all three.

Functional

ES6 has a new arrow function syntax, one most JavaScript programmers who have been keeping up already know pretty well.

let f1 = x => doSomething(x);
let f2 = (x, y) => doSomething(x, y);
let f3 = () => doSomething();

let identity = x => x;
let noop = () => {};

This is generally considered functional, but combine it with Array.prototype.{map,reduce}, and it'll start really looking more functional:

// generically
let doubleGeneric = xs =>
    Array.prototype.map.call(xs, x => x*2);
let doubleArray = xs => xs.map(x => x*2);

let sum = xs => xs.reduce((x, y) => x+y);

As you might have already noticed in the above examples, some of the Array.prototype methods are more generic as well.

Also, the two Underscore methods map and each could become a lot simpler to write:

function* range(n) {
    for (let i = 0; i < n; i++)
        yield i;
}

export const map = (xs, fn) => {
    let array = [];
    for (let i of range(n))
        array.push(fn(xs[i], i));
    return array;
};

export const each = (xs, fn) => {
    for (let i of range(x))
        fn(xs[i], i);
};

You could always use Array.from in each of these cases as well, making them far smaller and a little more functional (albeit a little slower):

export const map = (xs, fn) => Array.from(xs).map(fn);

export const each = (xs, fn) => Array.from(xs).each(fn);

There are also Promises, already known to be monads, and they're now in the standard library. It is easy to make a promisifying function for Node-style callbacks:

function promisify(fn) {
    return function (...args) {
        return new Promise((resolve, reject) =>
            fn(...args, function (err, ...retArgs) {
                if (err != null) {
                    reject(err);
                } else {
                    resolve(...retArgs);
                }
            }));
    };
}

// Example
let fs = require('fs');
let readFile = promisify(fs.readFile);

readFile('foo.txt')
    .then(data => doSomething(data))
    .catch(err => console.error(err));

There are also generators, which are lazy, while Arrays are eager. You can write equivalents to most Array.prototype methods easily for generators.

function* map(gen, fn) {
    let i = 0;
    for (let val of gen)
        yield fn(val, i++);
}

function each(gen, fn) {
    let i = 0;
    for (let val of gen)
        fn(val, i++);
}

function reduce(gen, fn) {
    gen = Generator(gen); // shallow copy
    let last = gen.next().value;
    let res = last;
    for (let val of gen)
        [res, last] = [fn(val, last), val];
    return res;
}

// Array.prototype.contains is ES7-specific
function contains(gen, ...vals) {
    for (let i of gen) {
        if (vals.contains(i))
            return true;
    }
    return false;
}

function* filter(fn) {
    let i = 0;
    for (let val of gen) {
        if (fn(val, i))
            yield val
    }
}

// etc...

I can't end this section properly without at least mentioning the new Array methods:

  • [].some(fn) - true if fn returns true for any element, false otherwise)
  • [].every(fn) - true if fn returns true for all elements, false otherwise)
  • [].copyWithin(target, start, end = this.length) - copies entries in-place from the range start to end to the range of same length starting at target. Example: [1, 2, 3, 4, 5].copyWithin(0, 3) //=> [4, 5, 1, 2, 3]
  • [].entries() - returns an iterator (like a generator) for the array
  • [].find(fn) - returns the first entry that fn returns true for, undefined otherwise.
  • [].findIndex(fn) - like [].indexOf(val), but for functions. Returns first index that fn returns true for, -1 otherwise.
  • [].keys(), [].values() - mainly for consistency with {Map,Set}.prototype.keys() and {Map,Set}.prototype.values().

Imperative

It is already pretty well established that JavaScript has its imperative components. There is no reason to cover this in detail; just look at some of the examples above. Sometimes, you have no choice but to split things into separate statements.

Object-Oriented

Yes, JavaScript has always been object-oriented since its creation, and it is well known that ES6 has its own class syntax.

class Foo {
    constructor(arg) {
        this.bar = arg;
    }

    sayBar() {
        console.log(this.bar);
    }
}

class Bar extends Foo {
    constructor(x, ...args) {
        super(...args);
        this.x = x;
    }
}

let bar = new Bar(1, 3);
bar.sayBar(); // prints '3' to console
bar.x; // 1

But, the new syntax also builds on JavaScript's object-orientedness substantially. Now, there are also static methods you can add to classes, and it is easier to extend classes (like above), so ES6 classes are a lot more declarative, clear, and concise. You can even subclass builtins now.

class Baz extends Foo {
    static from(obj) {
        return new Baz(obj.bar);
    }
}

// Even this is allowed.
class MyArray extends Array {
    constructor(prop, ...args) {
        super(...args);
        this.prop = prop;
    }
}

Conclusion

ES6 will add to the confusion of what JavaScript really is, albeit in an awesome way. There are three primary categories people typically try to lump JavaScript into, and they're all (mostly) right:

  • Functional: arrow functions, more generic Array methods, some new Array methods, lazy generators.
  • Imperative: relatively self-explanatory
  • Object-oriented: simpler class declaration syntax, more deeply integrated with the language, may make more parts of the DOM possible to implement in JavaScript.
    • DOM Level 4 will replace HTMLCollections and NodeLists with Elements, an actual ES6-style Array subclass with two additional methods: Elements.prototype.query() (akin to element.querySelector) and Elements.prototype.queryAll (akin to element.querySelectorAll). This will make the DOM even easier to work with and an even better fit for both functional and OO programming.

Tuesday, August 5, 2014

Society in a nutshell

There are two factions: people who religiously cling to the past, and the people who are disillusioned. These two seemingly endlessly conflict over most things. Then, there are the decisively ignorant. These people either pick a side but don't fight, or they disacknowledge the very existence of either.

Monday, July 28, 2014

I like ES6...works well, even for golfing (factorial demo hack)

Disclaimer: All code in this post is licensed under the BSD license.


Update: updated much of the code, made the JS smaller and the assembly half the instruction size. Also made the comments fit a little better space-wise.

Everyone knows about JavaScript and the basic factorial function, and here's the basic recursive implementation:

// ES5 and previous
function fact(n) {
  if (x > 0) {
    return n * factorial(n - 1);
  } else {
    return 1;
  }
}

// ES6
let fact = n => n > 0 ? n * factorial(n - 1) : 1;

But, I find this hack fairly cool: it basically takes enormous advantage of precedence and how logic statements work in ECMAScript. The hack assumes integer input.


// ES5 and previous
function fact(n) {
  return +(n < 1) || n * fact(n - 1);
}

// ES6
let fact = n => +(n < 1) || n * fact(n - 1);

The hack version also takes advantage of an implicit boolean-to-integer cast, which is usually quicker than a conditional. Code golfing is a little fun for these kinds of hacks, so let's compare a golfed C/C++ version to this ECMAScript hack unminified (using the ES6 versions):


int f(int n){int r=1;while(n--)r*=n;return r;} // Golfed C/C++
let fact = n => +(n < 1) || n * fact(n - 1); // Unminified ES6
function fact(n) { return +(n < 1) || n * fact(n - 1); } // Unminified ES5

And minified:

int f(int n){int r=1;while(n--)r*=n;return r;} // C/C++
function f(n){return +(n<=0)||n*f(n-1)} // Minified ES5 and previous
let f=n=>+(n<1)||n*f(n-1); // Minified ES6

Here's an explanation of the hack, comments inline:


// This works in all ECMAScript standards, from ECMAScript 3 through
// ECMAScript 6 and beyond.
function fact(n) {
  return +(n < 1) // This implicitly casts from boolean to
                  // integer, retaining truthiness.
                  // If true, this returns 1 and does not
                  // evaluate the right side.
         ||       // If false, evaluate the next part.
         n * fact(n - 1); // Here's some pseudocode explaining
                          // this:
                          //
                          // 1. Remember n in a pseudo-variable
                          //    x.
                          // 2. Decrement n by 1.
                          // 3. Apply the factorial function to
                          //    n.
                          // 4. Multiply it by the pseudo-
                          //    variable x.
                          // 5. Return the value.
}

Here's the function without comments:

function fact(n) {
  return +(n <= 0) || n * fact(n--);
}

let fact = n => +(n <= 0) || n * fact(n--);

You'll never beat assembly in speed, though... (this is written for x86 using Intel syntax)


; And almost in size...this is surprisingly short.
_fact: pop ecx    ; assumes cdecl calling convention, returns
       mov eax, 1 ; on eax
.loop: mul ecx
       loop .loop
       ret

Tuesday, May 27, 2014

User friendliness and SEO optimization for clients without JS using <noscript>, <meta>

The following is a simple HTML hack to really help with detecting clients without JavaScript enabled or supported and serve them better content accordingly:

In the <head>, add this code:
<noscript><meta http-equiv="refresh" content="0; url=www.example.com/no-js-version" /></noscript>
The URL can be any of your choosing, and it matters none what it is. It is just meant to point to a version that does not require JavaScript. This is best placed as the first tag after the <meta charset="utf-8" /> element in the <head>.

There is a caveat to this: it only validates as HTML5. This means nothing to modern browsers, but it could provide potential issues if compatibility with older browsers (e.g. IE8 or earlier) is needed.