Created
March 10, 2012 16:14
-
-
Save dherman/2011902 to your computer and use it in GitHub Desktop.
using -> for concise functions and => for TCP functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
}); | |
}); | |
} | |
}; |
For prototype methods, you don't want to use =>
because you want this
to be dynamic. But you could use ->
.
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)
}
For prototype methods, you don't want to use => because you want this to be dynamic. But you could use ->.
Sorry I meant ->
instead.
And probably skip / continue
is redundant anyway if you have filter
:)
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
Probably you should use
=>
form instead offunction
for prototype methods as well, otherwise there are just too many function forms in the same code.