Saturday, January 21, 2012

JavaScript WAT moments and Dart


There's a very funny 5 minute video by Gary Bernhardt from CodeMash 2012 which highlights a few WAT??!?! moments with some of our favoriate languages like Ruby and JavaScript. If you haven't seen this yet, take a few minutes and give yourself a chuckle.

Back? Cool. Let's map some of those JavaScript WAT moments to Dart and see how we do.

Example 1: Adding two empty arrays

Behold, the JavaScript:

[] + []

> "" // ?!?!?!

Not expected.

Behold, the Dart:

(note, List does not have a + operator, so here's the best we can do)

var result = [];
result.addAll([]);

print(result is List); // true.

Expected.

Example 2: Adding an empty array and empty map

Behold, the JavaScript:

[] + {};

> "[object Object]"  // ?!?!?!

That's right, a string. Not expected.

Behold, the Dart:

(note, Map does not extend collection, so not only can't we use the + operator, it doesn't make sense to directly add a Map to a List.)

var result = [];

[].addAll({}); // NoSuchMethodException: Map is not a Collection! Expected!

Not being allowed to add a map and array is expected. I am thankful the program stops if I try to do this.

Example 3: Adding an empty map and empty array

Behold, the JavaScript:

{} + []

> 0

The number zero. Not expected.

Behold, the Dart:

// nothing even close

There's no way to simply add a Map and a List. This makes sense, it is expected you can't just add a list to a map.

Example 4: Adding an object to an object

Behold, the JavaScript:

{} + {}

> NaN

Which, as the video says, is probably right. :)  However, still unexpected that this is allowed to run.

Behold, the Dart:

// nothing comes close

Neither Map nor Object have implemented the + operator, so it's impossible to try to add two objects or two maps together. It is expected that you can't simply add two arbitrary objects.

(Note: Dart does support the ability to define an operator method on a class. You are free to add plus or minus, for example, to your classes.)

Example 5: Subtracting a number from a string

Behold, the JavaScript:

"wat" - 1
> NaN

One could argue that yes, indeed, the result of subtracting a number from a string is not a number. I will grant you this. However, the fact that this line is even allowed to run and return a result is not expected.

Behold, the Dart:

var result = "wat" - 1;

// analysis will generate warning: string has no operator method '-'

// attempting to execute this will throw NoSuchMethodException

Dart will warn you that string does not have an operator method '-', but it will let you execute the program (due to types not affecting the runtime semantics of the code, because Dart embrases optional types.)

If you don't heed the warning, the above code will fail with a NoSuchMethodException, because string doesn't have a minus operator. This is expected.

Summary

The point of this post isn't to pick on JavaScript specifically, as every language eventually ends up with odd puzzlers. The point of this post is to instead remind you that there are people working very hard to reduce and remove these subtle and confusing situations from your next web programming language.

We can indeed demand more expected results from our languages and tools, and we should demand more early errors from obvious mistakes.  We need to demand less WAT?!?! moments in web development.

(BTW if anyone knows of the ES6 aka JavaScript.next aka Harmony versions of the above code, I'll be happy to include them. I'm curious if the latest work on the future of JavaScript addresses the above issues.)

6 comments:

Anon said...

"use strict";

Foo said...

I'm sorry, but while I look forward to seeing Dart in action, and am following this blog, I think that article and those comparisons are extremely stupid. You're doing stuff that nobody would ever do in JavaScript and complaining about the results and showing that Dart is oh so better and doing weird stuff like that. The only thing useful is maybe adding two arrays together. But you're doing it with a function! Guess what, you can, too, in JavaScript.

[].concat([])Don't complain about a JavaScript operator's inability to solve a problem, then turn around and do it with a method in Dart when JavaScript can do the same.As I said, I have no problem with Dart and am looking forward to seeing how it fares, and have read your summary and your explanation for this article, but I still don't think it's okay to make something such as blatant to promote your language.

sethladd said...

indeed! Can you elaborate on how this will address the WAT moments? I'll be happy to update the post above.

sethladd said...

Hi Foo,

Please remember the original WAT video was a bit tongue in cheek. If you haven't seen the video, please watch it first. The rest of this blog post will make more sense.

Regardless, I certainly hope no one is going to write code like this in real like. Alas, I'm sure it happens all the time inadvertently, and subtle bugs crop up because of it.

Foo said...

Hi, I'm sorry I got a big angered. I hadn't seen the video. I get the humour now. As for ES5 solutions to your problems, [].concat([]) applies to concatenate arrays.

Brent Amrhein said...

I had my doubts about Dart at first; not because I thought it was a lackluster language, but because (as I'm sure everyone working on it realizes) of the monumental task of getting browser vendors and web developers to adopt a new language.

However, the more I hear and read about Dart, the more I like it. I think it does a lot of things right and that it would be A Good Thing if it obtained widespread adoption. The fact that Dart doesn't fail those Javascript undefined behavior tests shows that it's a well-designed language. And I would expect nothing less from the guys working on it. :)