Hacker News new | past | comments | ask | show | jobs | submit login
Douglas Crockford on Fat Arrow Functions in JavaScript (yuiblog.com)
126 points by jashkenas on March 31, 2012 | hide | past | favorite | 60 comments



The proposed function syntax looks exactly like C# lambda functions. Even the (this, x) => {} format is similar to how C# extension methods work. Extension methods require "this" to be the first parameter and define what objects the method can act on.

It's really interesting to see that bleed over from a completely different type of language.


In Javascript it wouldn't be an extension method though, but a function with a dynamically bound `this` (similar to current function behavior)


Right. I just meant to point out the syntax similarities.


Just realized that Crockford didn't link to it in his post. Here's the full proposal that Brendan Eich added to the ES Wiki: http://wiki.ecmascript.org/doku.php?id=strawman:arrow_functi...


Was: From my understanding of binding, this proposal means that the fat arrow can't be used to define 'methods' on a prototype.

Edit: as per parent article, use (this, x) => { this.property = x; } instead of ->


That is usually not my problem -- I need it to bind this when I am making a for or map loop or registering a callback handler.


The part I found interesting was:

"However, we don’t want CoffeeScript’s ->, it’s confusing to have two arrows and dynamic this binding is an oft-fired footgun."


It looks like Eich's original pitch was for both => (lexical this) and -> (dynamic this), but the latter was cut for political reasons.

Out-of-band info from here:

https://twitter.com/brendaneich/status/186156717506166784

https://twitter.com/brendaneich/status/186160406300082176

https://twitter.com/brendaneich/status/186162306521120770

https://twitter.com/brendaneich/status/186162532367601666


Thanks. Interesting!


I didn't know what to make of that comment. Dynamic this-binding is used heavily in any OO javascript code; it's not a feature that should be ignored when designing the new syntax.

To me, writing 'this' as part of the parameter list for methods is more confusing than having a second arrow operator.


I'd be interested to hear from any regular user of CoffeeScript who finds -> vs. => confusing.


The new functions do not have names, so you will need to use the old functions to write self-recursive functions.

Or you can use the Y Combinator for extra fun...

https://secure.wikimedia.org/wikipedia/en/wiki/YCombinator#E...


Can't you assign the function to a var and invoke that in the function body, like in Coffeescript? Otherwise I'm missing something.


Looks really similar to Coffeescript. Is it safe to say that this new Javascript feature is a direct result of Coffeescript's influence? I hope so: Javascript is full of little horrors like the 'this' keyword, and it seems like it took a whole new language to convince people that it needs fixing.


I think its absolutely because of languages like coffee script that JavaScript is changing, but don't take my word for it. You can find statments from standards makers to the same effect.


Really? I'd really like to see some references to that.

These kinds of changes have been floating around for javascript since long before coffeescript.


This is a great talk to watch about the development of JS. It's been a while since I watched it, but the point I was making, and the point I gleaned from this talk, is that new ideas need a test bed, and according to Eich Coffeescript is one of those places where new ideas are tested, and derived from.

http://vimeo.com/27911873

http://brendaneich.com/2011/08/my-txjs-talk-twitter-remix/


The Harmony project (named differently in the past) existed long long before Coffeescript.


I don't think it matters what came first. CoffeeScript has had a great effect on hearts, and minds because you can use it. It matters that CoffeeScript exists because people can wrap there head around new concepts and ideas. Only once people really understand an idea can we determine if it's good, or bad.

Fat arrow is well understood in the JS community because of CoffeeScript, and that is one reason why people are pushing for fat arrow to be accepted. I personally think CoffeeScripts has had a very large impact on the idea.


the this keyword still works exactly the same, just a terse syntax for functions and for function binding to the current scope.

currently, function(){} is the exact same as the proposed ()->{}, and (function(){}).bind(this) is the exact same as ()=>{}


This is not just about syntax. Unless using bind somehow grants the mentioned property that

>"Fat arrow functions do not have prototype properties, which makes them cheaper to make. They are immutable."


granted, but that sounds more like a micro optimization rather then significantly changing the behavior of the language


Fat arrow and yield operator? Looks more like c# to me...


yield has been in Mozilla for ages, like, Firefox 2.x. The inspiration was python's yield.


I think it's safe to say. Arrow functions have existed in many different languages, but this particular flavor of using the fat arrow to declare a "lexical `this`" function, where the value of "this" within the function body preserves the value of "this" outside, is in CoffeeScript:

http://coffeescript.org/#fat_arrow


Jeremy, would you mind sharing what the inspiration was for CoffeeScript's fat arrow? Was that token inspired by another language or was it something you just came up with on your own?


Sure -- the syntax for arrow functions has been floating around for ages, in Haskell, C#, and probably most relevant for me, the "stabby lambdas" in Ruby 1.9.

One of the first ideas with CoffeeScript was to simplify function syntax, mostly because JavaScript's anonymous functions are so useful and pervasive that you end up with a lot of this:

    _.each(toRemove, function(key){ delete data[key]; });
... where the "word" function there doesn't really tell you anything meaningful about what you're trying to accomplish.

Arrows were appealing for a shorthand function syntax because of their visual representation of what happens in a (pure) function. Input goes in one side, output comes out the other. The input determines, or points to, the output. Since we use parentheses symmetrically to group parameters to a function, both when you define a function and when you call one, we arrive at this:

    (input) -> output
... or with our initial example:

    _.each toRemove, (key) -> delete data[key]
That was the thinking. CoffeeScript actually originally used => for all functions, but the fat arrow distinction was introduced when we introduced bound (lexical "this") functions as an alternative to normal (dynamic "this") functions.


Thanks for the detailed response. I thought it might have been inspired from Haskell or Ruby, but was surprised to find out that C# has a similar syntactic feature. So I was curious if there was an "official" etymology. Sounds like an amalgamation of all of the above.


At this point it feels like the next version of Javascript should just standardize CoffeeScript syntax and add a few much needed features CoffeeScript can't currently do because of JS limitations.


Fat arrows are one of the selling points for CoffeeScript, if you don't want to wait for ECMA6.


Doesn't fix the inefficiencies.


Recent versions of CoffeeScript greatly improved compilation of fat arrows.

This:

    x = (a) =>
      y = (b) =>
        z = (c) =>
          @q * a * b * c
Becomes this:

    var x,
      _this = this;

    x = function(a) {
      var y;
      return y = function(b) {
        var z;
        return z = function(c) {
          return _this.q * a * b * c;
        };
      };
    };
Instead of this:

    var x;
    var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
    x = __bind(function(a) {
      var y;
      return y = __bind(function(b) {
        var z;
        return z = __bind(function(c) {
          return this.q * a * b * c;
        }, this);
      }, this);
    }, this);


Taze is (presumably) talking about the inherent inefficiency of all those functions having prototypes.

(You know, the thing that was mentioned in the linked article?)


Can't wait for this to happen and gain widespread browser support so I can actually use it.

JavaScript is a beautiful language trapped in a lame syntax, peppered with poor semantic choices based on what was considered "just the way it is" back then.


If its that important you could just use Coffescript while you wait.


There are things about coffeescript that I just don't think are good ideas, like "unless" or "if" at the end. The person reading the code will think "Ok, now I'm doing x ... oh wait I'm not". the flow of it is just backwards.

The "myFunction(item) for item in array" syntax also seems wrong way around. You use "item" before you say what it is.

I'm not an expert. These are just initial impressions, but coffeescript seems to have some good ideas, but tries to do too much. It would be interesting to see what thought process went into deciding to include certain constructs. Was it just an experiment? Are there reasons that might persuade me?

Ultimately the better JavaScript is also going to be JavaScript.


    > It would be interesting to see what thought process 
    > went into deciding to include certain constructs. 
Happy to oblige. There's plenty of reading material and conversations about most language decisions available here:

https://github.com/jashkenas/coffee-script/issues?direction=...

As to the existence of (optional) postfix "unless" and "if" -- does it also sound backwards to you when someone says:

    "Call your mother if it's her birthday."
... in English? If that doesn't sound so crazy, then consider the CoffeeScript:

    call mom if mom.birthday.isToday()
It's a little thing, that hopefully you can take advantage of to make short conditionals more readable then the JSLint-style JavaScript:

    if (mom.birthday.isToday()) { call(mom); }


The problem is we're mainly conditioned to expect the condition up front, notwithstanding Perl's initial slide down this slippery slope. Ugly syntax seems an argument for improving the syntax, not changing the grammar.

    if mum.birthday.isToday(): call(mum)


Does a language need three ways to say "if x do y" ? or maybe there's an "unless !x do y" construct and it's 4 ways.

This to me looks like going out of your way to have lots of ways to do the same thing. I never cared for it in PERL either.

The argument that "it reads like English" is not one that I like much - The history of making programming languages read like English is a long succession of dead ends. Programming languages work more like formal maths proofs than they do like English prose. Rather make the language readable on its own terms.


> The history of making programming languages read like English is a long succession of dead ends.

There certainly have been notable failures, such as Applescript, but I find it hard to dismiss Coffeescript, Ruby, SQL and FORTRAN which have all been quite popular.


I like SQL, not for the english-ish keywords, but for the strong mathematical underpinnings.

You left out a notable example of Cobol - Which would you rather read: "Add 1 to someValue Giving someValue", or "someValue++" ?


"myFunction(item) for item in array" is a list comprehension a lot of languages have ... among them python and haskell. It's really nothing special.

Hell, it's very similar to how "map" works in most functional languages -> "map function items"


I can see how map works. It could even be done in JavaScript: map(myFunction, items);

"myFunction(item) for item in array" looks like "call myFunction on "item", which is not yet defined... oh now it is." It's backwards.


Something about using a language that is essentially syntax sugar for a different language just doesn't sit right with me.

I'd much rather they fixed javascript, than use coffeescript.

Although this might be unfair to coffeescript, I haven't given it a proper try-out yet :)


All languages above assembler are as syntax surgary as coffee script.


Don't be silly — assembler is just sugar for machine code.


That's not true at all, even something as low-level as C shifts the semantics dramatically away from how assembler works.

C functions conceptually in a half-assed attempt at making the computer behave marginally more like a Harvard Machine than a Von Neumann one.

OTOH, coroutines are easier to bring about in assembler than in C.


But then you have to wait for browser adoption. Maybe you'll safely be able to use this syntax in 4 or 5 years.


There's other places where we see JavaScript. For example in node.js, where you could use this stuff in production immediately.


Poor syntax and poor semantics. What is the missing part that makes it beautiful?


It is very widely deployed and will work on almost all client devices.


That dosen't really say much about the language itself though, which I think was what was being called 'beautiful' (as opposed the ecosystem).

Besides, couldn't the same argument be made about C? Sure I know a lot of people 'like' C, but I don't think I've ever heard of it being referred to as 'beautiful'...


C isn't really beautiful anymore but to somebody used to program in assembly it properly is beautiful.


C's beauty is in its simplicity.


Nice expressivity, mostly functional, fun to use, etc.


It has closures, I don't really know if it has anything else in common with a functional language...


Holy shit something that has been around for a while and works in all browsers now with coffeescript is now something we may be able to use with regular javascript in like 10 years! What's next, a for loop? Am i pushing it too far?

(flame prevention: this is kind of a joke. i understand that it actually is pushing towards a better language, it's just such a slow and painful process compared with just using coffeescript)


It's nice that somebody like Crockford writes an article like this, telling us how to actually use the new syntax. The original ES Wiki article is probably great for browser vendors but i didn't quite get it the first time i read it.


It sounds like people will prefer the (a,b) => {} syntax over function (a,b) {} simply because it's more concise and looks better, not because of its usefulness.


Sometimes concise is (arguably, of course) better.

Whenever I pass a simple and short function, for example as a predicate to grep/filter or as a tiny implementation for map/reduce I feel that "function" is half of what I type - and distracting. Worse, explicitly "return"ing adds more noise.

Most of my anonymous functions are really, really small. If they are usually on the level of "d % 2 == 0" or "d.slice(42)" then removing the overhead of "function (d) { return" seems a good idea. Not a huge deal, but nice nevertheless.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: