On Github dilvie / slides-dynamic-duo
"Empty your mind, be formless. Shapeless, like water. If you put water into a cup, it becomes the cup. You put water into a bottle and it becomes the bottle. You put it in a teapot, it becomes the teapot. Now, water can flow or it can crash. Be water, my friend." - Bruce Lee
Eric Elliott
"A helpful analogy to understand the value of static typing is to look at it as putting pieces into a jigsaw puzzle. In Haskell, if a piece has the wrong shape, it simply won't fit. In a dynamically typed language, all the pieces are 1×1 squares and always fit, so you have to constantly examine the resulting picture and check (through testing) whether it's correct." — Bryan O'Sullivan, et al. "Real World Haskell"
It's impossible to write large programs in JavaScript because there is no way to know if your program is even passing around correct types.
37Signals, Adobe, Dow Jones, eBay, Flickr, Paypal, LinkedIn, Groupon, Microsoft, Trello, Uber, Voxer, Yahoo!, Yammer, Walmart all have substantial projects written in JavaScript (Node).
That warm cozy feeling you have about your compile time checking is a false sense of security.
Type correctness does not guarantee program correctness. #belikebruce
"The first step is fully admitting that the code you write is riddled with errors." - John-Carmack "Static Code Analysis" blog post (must read)
"But... but... WHY do all that if you can just let the compiler do static analysis!?" - Dude looking at his cell phone a few minutes back
function foo(options) { //... } var myThing = foo({ bar: ? type ?});
"Kill yer crew before ya sail!" - Colt McAnlis "The Joys of Static Memory JavaScript" #perfmatters @duhroach
"Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp." - Greenspun's tenth rule
int increment(int x) { int result; result = x + 1; return result; }
enum type { TYPE_INT, TYPE_LONG, TYPE_FLOAT };
wait for it...
void increment(enum type t, void *x) { switch (t) { case TYPE_CHAR: (*(char *)x)++; break; case TYPE_INT: (*(int *)x)++; break; case TYPE_FLOAT: (*(float *)x)++; break; } }
Tada! Simple!
incr(TYPE_INT, &i); incr(TYPE_LONG, &l); incr(TYPE_FLOAT, &f);
function increment(x) { var result; result = x + 1; return result; }
But there's only one number type in JS, so this isn't fair. But wait! ...
function increment(x) { var result; // Now with string concatenation! result = x + 1; return result; } increment('1'); // 11? // WTF, JS! You're killin' me here!
That awkward moment when your example proves the counterpoint...
An approximation of ES6 String.prototype.contains()...
if (!('contains' in String.prototype)) { String.prototype.contains = function(str, startIndex) { return ''.indexOf.call(this, str, startIndex) !== -1; }; }
if (!('contains' in Array.prototype)) { Array.prototype.contains = function(str, startIndex) { return ''.indexOf.call(this, str, startIndex) !== -1; }; }
String.prototype.map = function () { return [].map.apply(this, arguments).join(''); }; '123'.map(function (n) {return +n + 1; }); // '234'
Please don't extend built-in prototypes
(except for standard polyfills)
fn([x], fn(x):*): [x]
e.g.: .map(), .filter()...
fn(el [, options...] [, prev] [, index] [, list]): x
fn(el [, options...] [, prev] [, index] [, list]): bool
Truthy = on the list
fn(el [, options...] [, prev] [, index] [, list]): x
Accumulates a single value to return.
function sum() { var i = 0, result = 0; while (i < arguments.length) { result += +arguments[i]; i++; } return result; } sum(2, 2, 2); // 6
var item1 = { name: 'Gibson Les Paul', price: 4299.95 }, item2 = { name: 'Epiphone ES 339 Pro', price: 395 }; sum(item1, item2); // NaN
function sum() { var i = 0, result = 0; while (i < arguments.length) { result += +arguments[i].valueOf(); i++; } return result; }
function item(options) { var instance = Object.create(item.prototype); instance.name = options.name; instance.price = options.price; return instance; } item.prototype = { valueOf: function () { return this.price; } };
var item1 = item({ name: 'Gibson Les Paul', price: 4299.95 }), item2 = item({ name: 'Epiphone ES 339 Pro', price: 395 }); sum(item1, item2); // 4694.95
sum(1, 2, 3); // 6
template<std::CopyConstructible T> requires Addable<T>, Assignable<T> T sum(T array[], int n, T result) { for (int i = 0; i < n; ++i) { result = result + array[i]; } return result; }
(Source: generic-programming.org)
var burger = { pickels: 3, lettuce: 1, tomatoes: 1, onions: 1 };
function addToppings(sandwich, toppings) { var topping; for (topping in toppings) { if ( toppings.hasOwnProperty(topping) ) { sandwich[topping] = toppings[topping]; } } return sandwich; } var myBurger = addToppings(burger, { cheese: 1 });
var myModel = _.extend(Object.create(model), Backbone.Events);
"Be like water making its way through cracks. Do not be assertive, but adjust to the object, and you shall find a way around or through it. If nothing within you stays rigid, outward things will disclose themselves." - Bruce Lee