hybridgroup/cylon — pull request #246 by stewart (2014-12-17 23:13:29+00:00)
Title: Add Lo-Dash

Adds the Lo-Dash utility module, to help ensure our iterators are consistent and simplify code where possible to prevent ambiguity.

A couple of gems:

- `_.map` can be used in the same matter as Ruby's Enumerable#map, but also allows for key fetching.
This allows for the following code simplification:

```javascript
var fns = [];

for (var bot in this.robots) {
var robot = this.robots[bot];
fns.push(robot.halt.bind(robot));
}

// becomes

var fns = _.map(this.robots, "halt");
```

- `_.forEach` iterates just as well over arrays as objects, meaning we don't have to keep track of prop/key assignment

```javascript
var obj = {
"TestBot": { start: function() {} },
"NewBot": { start: function() {} }
};

_.forEach(obj, function(bot, name) {
console.log(name);
bot.start();
});

// calls #start() for each bot, and logs "TestBot" and "NewBot" to the console
```

- `_.invoke` calls a function on each value of a passed array or object.
If a string is passed, it's assumed to be a function property.
This simplifies the following code:

```javascript
var devices = [],
connections = [],
n;

for (n in this.connections) {
connections.push(this.connections[n].toJSON());
}

for (n in this.devices) {
devices.push(this.devices[n].toJSON());
}

return {
name: this.name,
connections: connections,
devices: devices,
commands: Object.keys(this.commands)
};

// becomes

return {
name: this.name,
connections: _.invoke(this.connections, "toJSON"),
devices: _.invoke(this.devices, "toJSON"),
commands: _.keys(this.commands)
};
```

- `_.include/contains` is a simpler, easier to use presence checker for arrays than `Array#indexOf`

```javascript
["robot", "name", "adaptor"].indexOf(opt) < 0;

// or

!!~["robot", "name", "adaptor"].indexOf(opt);

// becomes

_.contains(["robot", "name", "adaptor"], opt);
```

- `_.result` fetches a property from an object, returning the value directly if it's a primitive, or calling a function if one is found.
I've [added it to the Robot constructor](https://github.com/hybridgroup/cylon/commit/c9e16fe8c220362d2f990d2e68f934f732fa64ef?diff=split), to simplify fetching of `opts.commands`

```javascript
var object = {
'alpha': 'hi there',
'bravo': function() {
return this.alpha;
}
};

_.result(object, 'alpha');
// 'hi there'

_.result(object, 'bravo');
// 'hi there'
```

There's probably a few other places in Cylon this can be added (the API comes to mind) but I hope this nailed some of the more important parts.

The `lodash.js` file added in `lib/` will load the standard ES5-based version of Lo-Dash on most environments, and the backwards-compatible version for platforms like Tessel, which may not support all latest language features.

Other potentially useful functions can be found in the [Lo-Dash docs](https://lodash.com/docs).