Thursday, May 21st, 2009

Cramdas; Don’t mess with the semantics of function, just let me stop typing it so often

Category: JavaScript

<>blockquote>

There are two types of code. A large pile of crap code, and a small pile of crap code. Favour the small.

The above sentence was explained to Ben and I from a top notch IBM engineer who has written more code than I have had hot dinners.

Less code is good. Less to read, easier to understand, and as Alex mentions, it matters even more for JavaScript client side developers:

JavaScript is different. Unlike nearly every other language, the terseness of JavaScript code is a key determinant in the performance of a web application. The bigger your scripts, the slower your app loads. It’s as simple as that.

This comes from his proposal for JS Lambdas (or Cramdas). He continues:

It’s a crime, then, that we still have to type:

javascript
< view plain text >
  1. node.addEventListener("click", function(evt){ /* ... */ }, false);
  2.  
  3. // or
  4.  
  5. [/* ... */].forEach(function(i){ /* ... */ });

He then goes on to discuss the fact that he doesn’t want to get into arguments on what lambda means, but rather doing something more simple…. let’s just keep it simple:

The best that Erik and I could come up with that is relatively unambiguious for parsers, doesn’t introduce hard-to-type characters on certain keyboard layouts, and doesn’t mess with the semantics of function(){} is this:

javascript
< view plain text >
  1. // empty function body, zero arguments
  2. var lambda = #(){ /*... */ }
  3.  
  4. // empty function body, arguments list elided away
  5. var lambda = #{ /* ... */ }
  6.  
  7. // we can re-write the previous examples as:
  8. node.addEventListener("click", #(evt){ /* ... */ }, false)
  9.  
  10. // and
  11.  
  12. [/* ... */].forEach(#(i){ /* ... */ })

The syntax is a tough strange at first, but you can’t argue with the terseness. We use $ for document.getElementById-ish stuff, so how about #() for function()? I think I prefer it to other options like (evt)->{}. What would you like?

Related Content:

Posted by Dion Almaer at 9:23 am
29 Comments

+----
1.9 rating from 78 votes

29 Comments »

Comments feed TrackBack URI

personally, I really like groovy closure syntax:
{foo, bar -> foo.doSomthing(bar);}
or with no args, just:
{alert(“hello!”);}

Comment by genericallyloud — May 21, 2009

absolutely ridiculous.

Comment by nataxia — May 21, 2009

I think this is on a short path to creating something similar to Perl’s library of endlessly confusing shortcuts, that in the end make the code shorter, but less readable:

while () {
print “$.\t$_”;
}

Comment by danospv — May 21, 2009

So the crux of the article is that he’s suggesting we replace the word “function” with “#”. Genius…

Comment by willbo — May 21, 2009

# would be fantastic, I write code like your samples at the top, almost every day. Having something like #() would be great.
Trying it out myself though, defining a function #() causes syntax errors – maybe I’m going in the wrong direction. however, in the meantie I’m going to implement something like an f() (whatever doesnt conflict with existing code in my library of choice, MooTools)

Comment by Snowfruit — May 21, 2009

If you like to write less code, make functions that can take either a function or a string of code.

function each (a, js) {
if (typeof js === 'string') js = new Function('with(this){'+js+'}');
for (var i = 0, n; n = a[i++]; js.call(n));
}

This lets you write:

each(document.myForm.elements, 'disabled = false');

Comment by hlindqvi — May 21, 2009

hlindqvi:

I agree that’s even shorter and nicer. Dojo support this for many array operations, e.g.:

dojo.query(“.foo”).forEach(“console.log(item);”);

It’s useful in it’s way, but I find more often than not that what I *really* want is the ability to enclose some state. Since the string-based version can’t be a closure, it looses half of it’s function-ness, often causing me to write everything out the long way. Ugg.

Regards

Comment by slightlyoff — May 21, 2009

Ok… so what he’s proposing is replacing (or being able to replace) the function keyword with a hash char… Why only a single keyword? I would love to have _all_ keywords eliminated (or at least the ones used in for structures) and replaced by a special char!


for () {}

could be:

@ () {}

and

if () {}

could be:

? () {}

Words in my mind should be reserved for variable naming (and method names etc).

Comment by rasmusfl0e — May 21, 2009

@slightlyoff: String-based version means eval. Please consider doing:

dojo.query(”.foo”).forEach(console.log);

Comment by nasp — May 21, 2009

These kind of ideas are usually thought up by programmers that build applications fast and then quit their job before they have to maintain their own code whilst still having ace programming credentials.

http://thedailyajaxian.com/ is full of those ideas.

On the otherhand… would be great for GWT-like frameworks.

Take your pick.

Comment by BenGerrissen — May 21, 2009

IANAPLD* but it seems to that at least with JavaScript used in over the wire applications (like websites) the place to add terseness is in the build process. The function keyword does a very good job at expressing what it does, and is understood universally by programmers.

I’m open to the idea of terse aliases that can be substituted at build time for keywords, but in development use an IDE that supports auto-complete of known symbols/keywords and leave it at that.

*I am not a programming language designer

Comment by sashasklar — May 21, 2009

3 thoughts:

WOW, reminds me in part of why PERL is a write-only language.

To some degree anyway, javascript needs to be easy for beginners. Since the VAST majority of javascript programmers are beginning programmers.

If all the above offers is a little less typing and no real new semantic tools it’s useless. That does appear to be the case.

Comment by mojave — May 21, 2009

It never ceases to amaze me the fascination people have with “typing less” as if it somehow translated to less code. map, forEach, etc. have real uses: these are actual new concepts that reduce boilerplate and make code more understandable to the reader. But reducing every conceivable language construct and function call to a single character without changing the way it works seems like such a waste of energy.

Comment by tolmasky — May 21, 2009

Personally, I would like a nice juicy pussy…but since the topic is lambdas, I don’t think it matters what all those folks like (since no symbol on the keyboard looks like lambda (->?, really?)) – what matters is the fact that JS (or Ecmascript) will probably not be changed just because a bunch of nerds opened a post about “how long the word ‘function’ is”.

Comment by moshenick — May 21, 2009

nasp:

It means at least one function compilation, yes, but eval isn’t the evil you’ve been lead to believe. You can obviously do:

dojo.query(“.foo”).forEach(console.log, console);

today. With a better JS version, you might be able to do:

dojo.query(“.foo”).forEach(console.log.bind());

But most browsers treat the console object a funky host object that you can’t really treat like a normal JS scope, making this example particularly tricky.

Regards

Comment by slightlyoff — May 21, 2009

mojave:

The only reason it won’t offer new semantics is that JS functions are already “right”. They’re scopes, support var-args and named slots, handle return sanely, and are useful as closures. It seems clear that the ES working group wants to do SOMETHING here, and most of the syntaxes proposed come with *broken* semantics WRT function(){}. On balance, then, I’d prefer a better way to say function(){}.

Different semantics for the sake of being different != good.

Regards

Comment by slightlyoff — May 21, 2009

Here’s an idea. Throw out your modems and quit worrying about saving a few kb here and there!

This debate seems really short sighted to me. Let’s suppose that by this afternoon, we all decide on the best new minimalist syntax for functions, loops, conditionals, and everything. Now, how long before we can start using it? Considering 90% of us still need to support an 8 year old browser, it won’t be soon. By the time enough browsers support the new syntax, the whole point will be moot because everyone will have broadband. I’m pretty sure everyone outside of the US has it already.

Comment by okonomiyaki3000 — May 21, 2009

rasmusfl0e: ? is already used as if operator. var foo = bar ? foobar : baz;

Right now it’s probably easier for your mind to read function but # sounds great, I like my code to look like it went through a compressor.

Comment by Jadet — May 21, 2009

I propose:

\x y -> x y

which, when translated to JS, becomes:

function(x) { return function(y) { return x(y); }; }

Comment by chiaroscuro — May 21, 2009

chiaroscuro:

Hrm. That syntax uses new semantics to denote passing a function in. That’s not the way “lambda” is interpreted in many other languages, nor does it seem useful on the face of it. Perhaps the bigger issue is that the “\” char means a way to start a Unicode sequence in JS strings. Not a killer by itself, but when coupled with the alien-ness of not having arguments be enclosed by “(” and not being able to denote the end of multiple statements (your proposed syntax has no way to say “this is a multi-line block of code”), it seems to violate the principle I proposed for any viable alternative: it shouldn’t expose different semantics.

You, obviously, disagree that that’s a good goal, but I’d like to see how the syntax you propose makes life easier, e.g., in forEach() callbacks.

Regards

Comment by slightlyoff — May 22, 2009

@jadet: … which is why ? would be a perfect replacement for the if keyword.

The point of my comment was to eliminate the need for a reserved keyword list that forces programmers to do things like: for -> htmlFor, class -> className. I know these things are second nature to everyone by now – but if they are going redo js (or ecmascript) they might as well throw out all the quirky stuff in the proces.

Comment by rasmusfl0e — May 22, 2009

I have many issues with this approach, but more so the quote, “We use $ for document.getElementById-ish stuff, so how about #() for function()?” bugs me the most. It could be argued that since $ is actually an alias for a method, and more specifically, an alias for a method being called on a specific instance of an object, that it is ok. It could easily have been elem() and everyone could have saved 19 keystrokes.

However in the approach, # would be an alias for a reserved keyword. A savings 7 keystrokes, which I guess is good if you are renting your keyboard and want to keep the miles down, or texting code to a colleague. However it reduces the readability of the language; which it should be noted, a lot of the JS ninjas do not care about. In the “real” world, and not the super ninja one, most businesses do not have these ninjas. So as we reduce readability we also reduce the amount of people in the workforce that actually UNDERSTAND what is going on. (Do not confuse that with the number of people that will try to do it)

So how about people involve their selves in either the EMCAScript standards group to introduce ACTUAL lambda expressions (In fact that is not even a lambda expression) or spend that time and effort making a really good JS compressor and leave the language alone.

Comment by slackbits — May 22, 2009

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.

Comment by trav1m — May 22, 2009

There were a couple threads about syntactic sugar on the es-discuss list when Brendan brought up lambda syntax as something like “weekend bike shedding fun”. The thread was over 100 posts and lasted much longer than a weekend. Some of the suggestions here in the comments were already rejected for good reason in the es-discuss threads.

No matter what short syntax for lambdas was proposed there were parsing problems. Please read the es-discuss threads. What was amazing to me was the thought pattern of developers. Someone claimed that “this syntactic sugar is the sweetest.” Then someone would point out there were parsing problems. So another set of characters was proposed and then shot down. The problem went on repeatedly. The lesson to be learned, I thought, was don’t try to go for some encrypted ascii syntax for lambda because it might have implications you have not yet thought about.

It is easy to add lambdas to JavaScript without adding any new parsing problems. Just add the keyword “lambda” and use “lambda(){}” for them. Leave function syntax alone and avoid adding unforeseen problems to a language that already has its fair share of problems.

If the gripe here is just about having to type a long keyword like “function” and send it over the wire then using text editor macros and gzip should solve those problems They both reduce the burden of repeated patterns.

Comment by PeterMichaux — May 22, 2009

Inventing a terse syntax to compensate for poor language performance is a bad idea. Obscure syntax leads to errors.

“Make it right before making it fast” and “Keep it right when you make it faster”

C’mon guys, this is basic stuff.

Comment by TD — May 22, 2009

I am sorry to tell, but most of the comments came from people who never tried the functional programming before.

Yes, the conciseness depends on how much code you need to digest before getting to the idea of an algorithm (hint: too much fluff and a reader is lost). Yes, it is possible to make a program cryptic with too much “compression”. No, Alex didn’t propose new language, new semantics, nor new features. All he asked about is to reduces the unnecessary typing of “function” keyword with an alias (“#” in his case, there are other proposals).

Why “function”? Because it is the worst offender in JavaScript. If you have 5 lambdas in one statement “function”s (and “return”s) will bury you. What about making five independent local functions, and use them instead of inline functions? In some cases such decomposition makes code harder to understand. Again, it doesn’t sound right to create one-off entities — extra fluff, the nagging doubt that they will be used in more than one place, and so on. That’s why we write “a = 5 * b + 1″ instead of “var five = 5, one = 1; a = five * b + one;”.

PS: Another feature that can improve the overall conciseness would be operators. When used correctly by professionals in proper contexts they can do wonders. But Alex didn’t go there, so let’s skip it for now.

Comment by elazutkin — May 23, 2009

All he asked about is to reduces the unnecessary typing of “function” keyword with an alias (”#” in his case, there are other proposals).

I agree, that in the hand of proffesionals it’s a great tool, 99% of the javascript out there is not handled by proffesionals. In fact 60% of the JS proffesionals get to maintain are created by technical designers. I dread the day where I have to maintain bad code obfuscated by functional programming syntax.

Comment by BenGerrissen — May 25, 2009

isn’t this what the packers and compressors are for?

This has all been thought of and all been done before. And it makes a lot more sense for this stuff to be automated.

Comment by sylentmode — May 26, 2009

@BenGerrissen & @sylentmode: I think I addressed both issues/questions/remarks in my comment on Alex’ blog: http://alex.dojotoolkit.org/2009/05/on-js-lambdas/#comment-236051

In short:
* It is about conciseness and not about compression. Packing — how to pack keywords in JavaScript?
* Not all shorthand notations lead to obfuscation. Yep, there is a fine line between being short and being obfuscated, and in my opinion Alex’ proposal does not cross the threshold.

Comment by elazutkin — May 26, 2009

Leave a comment

You must be logged in to post a comment.