Infrequently Noted

Alex Russell on browsers, standards, and the process of progress.

Comments for On JS "Lambdas"


@Leo: Both "GZip and text editor autocompletion features" do not help with understanding of the code in question. If we are to turn the functional programming in JavaScript up a notch, we will see nothing but "function" words everywhere. Excessive bloat does make code less comprehensive. OTOH we should balance the act trying not to turn programs into obfuscated riddles. That's what Alex is talking about: no new rules, no new concepts, but more clarity by reducing unnecessary technicalities.
Chris:

I posted something not dissimilar to the ES lists some time ago, but it's not clear to a native JS parser what the {| production should mean. As we were talking through it, Erik pointed out to me that the { ... } syntax (maddeningly) seems to be taken by a anonymous block syntax that many JS interpreters already support but which doesn't actually DO anything. Grr.

As a result, both of those syntaxes would involve lots of look-ahead, which some implementers are (apparently) loathe to contemplate.

Regards

by alex at
If this ever makes it into EcmaScript, it would be great if it could avoid creating a new syntax and would instead adopt one that already exists in another "curly brace" language. I'm partial to the C# syntax for Lambdas myself.
Don't GZip and text editor autocompletion features make this proposal moot?
by Leo at
What a mess. Less code is not easier to read. When a small amount of code contains the same functional logic as a large amount of code, the short code is *harder* to read.

All languages have compilers to optimize their performance. Javascript has minifiers. I can have a large amount of human-readable source code while still sending a minimal amount of code to the browser. Please don't make things more complicated than they should be.

by Trav at
Leo:

They address size-on-the wire. They don't address human factors.

Trav:

I wrote one of those minifiers. You don't need to lecture me on the topic of what is and isn't effective in terms of reducing byte count ;-)

As for readability, it's a human-factors argument, and I'm arguing that seeing the word "function" all over the place really isn't as clear as you think it is. Java tends to be difficult to comprehend for similar reasons...stuff gets munged into structures that don't fit the intent as a side-effect of insufficient semantics married to bad syntax. JS is better on the functional side of things (the semantics are fine), but the sytnax is lousy. I'll absolutely agree that a non-lame class composition system (traits, anyone?) would go a very long way to addressing some of the bigger issues in the language, but if the WG is going to chew of lambdas (and it looks like they are), we should propose something that doesn't suck.

We can absolutely make both sides of the language easier to use at the same time. There's no either/or here.

Regards

by alex at
@Ian: I grabbed the most recent minified version of jQuery and did a simple:

sed -E -e 's/\sfunction\s/#/g' -e 's/\sreturn\s//'

...and got a savings of 4,220 bytes. So either the library grew an awful lot, or you were using a version that had been minified with something like packer using base62 encoding (which would have already removed nearly all uses of "function" and "return" at the cost of eval time). If the latter case is true, I don't think that's a very fair test, since the packed version is effectively doing (to a much greater extent!) what Alex is suggesting already.

This isn't to say that I think the size over the wire is really the most important consideration here (gzipping both versions reduces the difference to 339 bytes). The function(){} form in JS is as annoying as the array() literal in PHP.

The minified version I used: http://code.google.com/p/jqueryjs/downloads/detail?name=jquery-1.3.2.min.js

Packer: http://dean.edwards.name/packer/

by Shawn at
I am a big fan of Ruby's block syntax. Just " { ... } " and if you want arguments " {|x,y| x + y } ". Very clean, and very readable.

With that said, isnt there a javascript implementation of Ruby? HotRuby or something.

RIDICULOUS, get away from JavaScript thanks !
by LOL at
ben:

In the spirit of cathartic shortenings, may I suggest fu(ags){ ... }?

;-)

Regards

by alex at
I think I'm on Ian's side on this one. The function syntax seems properly expressive and makes it obvious what is happening in the code. I've never met anyone that was confused over what "function" meant. We really don't need to be making JavaScript less understandable by creating shortcuts to common keywords just because we're tired of typing them repeatedly. There's something to be said for the readability and maintainability of JavaScript code written in the way that it is right now.

In this case, "syntactic sugar" is really just "symbol replacement", and that doesn't seem to add much value on its own. Right now, "function" means "define a function"; I'm not sure how that could be any clearer.

Nicholas:

Language expressiveness is a balance between good Huffman coding (common stuff should be shorter than longer stuff) and descriptivness. This syntax is not "descriptive" in the sense that it doesn't say "function". It is, however, superior for all but the most trivial users of the language. At some point the word "function" actually begins to obscure the meaning of "I'm trying to create a closure as an argument", which happens quite often.

I understand the argument that says you might not need it, but improvements in turing-complete languages are rarely about "needs".

Regards

by alex at
+1 for Paul Barry's idea, adding implicit return to the short notation would be nice.

Just don't add it to the old functions for backward-compatibility.

by zimbatm at
Ian:

Yes. Really.

That is all.

by alex at
how about fn(args){...} - if the semantics aren't changing then fn would be a good choice since it is an already widely understood abbreviated form of function - just take a look at the lower left corner of your macbook ;)

if the semantics were to change as far as return values then you could use fn or function depending on your want.

it's also a good way to abbreviate some of those dirty "effin" curse words you use alex! perhaps some of your frustration could be released through your thoughts when everytime you needed a lambda, you would think "effin" and then you might be able to maintain a PG rating on your blog :P

by ben hockey at
Really? The strings "return" and "function" are keeping us up at night? I grabbed a minified copy of jquery 1.2.6 that happened to be lying around, it weighed in at 31111 bytes. With a trivial search and replace I replaced "function" with "#" and "return" with "", saving 71 bytes. Gzipped (like they'll be when they're served over HTTP to basically all browsers) the difference is 9 bytes.

I don't think that using the word "function" when declaring a function literal is a problem at all. It's not quite as concise as the syntax for other literals like objects, strings, numbers and regular expressions, but functions are a little more complicated, having arguments, a body and (sadly) optionally a name.

Perhaps it's just time to get an editor with macros :)

@Ian: to me it is not about the wire size (we have compression for that) but about cluttering the code with purely technical things making it less readable. I remember looking at some COBOL program: it could be read like a regular English text, yet I in order to grasp the idea of its algorithm I have to read pages and pages. That's why operators rule over function calls, and lambda will rule too.
Very good and very timely post.

Personally I want lambdas to achieve one goal: less typing. It means removing/bypassing both "function" and "return", if possible. At least in simple cases.

On ES4 mailing list several ideas were floated and one of them was to use a backslash:

(a, b)

or something like that.

But anything that makes using lambdas easier would get my vote (I am not on the committee, so it is not counted officially).

This would be nice. Another nice way to shorten it would be to make return optional, so I could say #(n){n*n} for a lambda that takes one argument and squares it. So as in most functional languages, the value of the last expression evaluated would be the return value. As of now, this would return the useless void/undefined value. Any chance of adding this in as well, or would this be considered fucking with the semantics of function?
Just for some more comparisons, Perl 5 just uses the keyword "sub":

my $lambda = sub

And Perl's @_ array works just like Javascript's arguments array.

Perl 6 goes further and has "blocks" and "pointy blocks":

my $lambda = { ... } my $lambda = -> $evt

by Michael Peters at
(a, b, c) => a+b+c;

http://msdn.microsoft.com/en-us/library/bb397687.aspx

by RichB at
You could also look at Smalltalk and see that for some uses of their lambdas (blocks), they actually just took "method names" (selectors). This let you flatten out your code, so all your callbacks weren't neccessariy buried on other methods, but were plain old methods. And there's obviously a slight performance penalty - someone has to lookup the function instead of just calling it.

There's another potential advantage to working this way; it avoids tight coupling of functions to their uses. If we ever get environments were reloading running code is possible and makes sense, have a layer of indirection between the functions will be nice. Otherwise all those folks with direct references to functions everywhere will find that those functions didn't get updated on the reload. At least, until someone gives us #become: (not holding my breath on that one).

Note that not all Smalltalk blocks were done this way, most weren't, but some were; my memory is that the UI toolkit I used most used them. (CommonWidgets - the Smalltalk version of today's SWT in Java, used them quite a bit)

I like where you're going with this, but I would vote against # as a symbol for function because its already used in so many other languages for 'comment'.
Why not something like Functional JS:

http://osteele.com/sources/javascript/functional/

Implicit parameters, implicit returns, and a lots of handy functions taking advantage of short lambdas.

It doesn't do any DOM-y stuff by itself, but I've been using it along with Prototype for some pretty happy code.