Skip to content

Instantly share code, notes, and snippets.

@dherman
Created March 10, 2012 16:14
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save dherman/2011902 to your computer and use it in GitHub Desktop.
Save dherman/2011902 to your computer and use it in GitHub Desktop.
using -> for concise functions and => for TCP functions
// 1. Shorter function syntax.
//
// This version does not respect "Tennent's correspondence principle" -- it's nothing
// more than syntactic sugar for the traditional function syntax. That means when you
// see the normal braced body of a function, whether it's a longhand function or this
// shorthand version, there's no difference: return, this, and arguments are all tied
// to the new function body, and there's no implicit returning of the last expression
// result.
a.some((x) -> {
if (invalid(x))
return true;
console.log(x);
})
// 2. Lambdas.
//
// This version is maximally concise, allowing only an expression for the body rather
// than a block statement. Between the "function" and "return" keywords, this saves a
// ton of noise and rightward drift. Another important benefit of the expression body
// is that there's no danger of leaking a completion value by accident. Braced bodies
// discard their result in shorthand and longhand functions, and lambdas return their
// result because their bodies are expressions.
a.map((x) => x * 17)
// Unlike the -> syntax above, lambdas do respect Tennent's correspondence principle:
// In particular, the this-binding remains the same as in the outer context.
CSVReader.prototype.read = function(str) {
return str.split(/\n/)
.map((line) => line.split(this.regexp));
};
// 3. Do-expressions.
// http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions
// This is not a function syntax but rather a way to execute arbitrary statements and
// still produce a result value. Currently, the only way to e.g. run a loop or bind a
// local variable before producing a result is to wrap the statements in an IIFE. But
// this messes up `this` and `arguments`. Do-expressions make this clean and simple:
var x = do {
let t = f();
t * t + 1
};
// 4. So happy together...
// Lambdas respect TCP, so you can return or break/continue to their outer functions.
// Compare and contrast this syntax with: https://gist.github.com/1609202
// Although do-expressions expose the completion value of a statement, they signal it
// explicitly with the keyword at their head. None of the function shorthands quietly
// leaks completion values without opt-in via `do`.
Mailbox.prototype.extractContents = function(contacts) {
for (let a = this.messages, i = 0, n = a.length; i < n; i++) {
a[i].headers.forEach((header) => do {
if (header.isSpam())
continue; // could use a label but unnecessary
let addresses = header.extractAddresses();
addresses.forEach((addr) -> {
contacts.add(addr.name, addr.email);
});
});
}
};
@Gozala
Copy link

Gozala commented Mar 12, 2012

Probably you should use => form instead of function for prototype methods as well, otherwise there are just too many function forms in the same code.

@dherman
Copy link
Author

dherman commented Mar 12, 2012

For prototype methods, you don't want to use => because you want this to be dynamic. But you could use ->.

@Gozala
Copy link

Gozala commented Mar 12, 2012

Also, I personally don't understand why continue break is so important, I'd rather see some standard functional
iteration alternatives to fulfill these needs:

Mailbox.prototype.extractContents = (contacts) -> {
  loop((headers, stop, skip) -> {
    loop((header) -> {
      if (header.isSpam()) return skip()
      let addresses = header.extractAddresses()
      loop(({ name, email }) => contacts.add(name, email), addresses)
    }, headers)
  }, this.messages)
}

@Gozala
Copy link

Gozala commented Mar 12, 2012

For prototype methods, you don't want to use => because you want this to be dynamic. But you could use ->.

Sorry I meant -> instead.

@Gozala
Copy link

Gozala commented Mar 12, 2012

And probably skip / continue is redundant anyway if you have filter :)

@Gozala
Copy link

Gozala commented Mar 12, 2012

In general I'd rather see more stdlib functions in ES.next solving issues than new syntax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment