11 comments

[ 2.8 ms ] story [ 31.0 ms ] thread
Good article. And I admire your cute and clever selection of fonts. No, seriously.
What a very cute and clever thing to say.
Linked [0] "Time Scheduler" is pretty cool but it crashed twice on Chrome, and also the time brackets can't be dragged. I had an idea a couple days ago for this exact 'app'; if it was a little more accessible/reliable, I might actually use it.

[0] - http://timesched.pocoo.org/

It was quite literally a weekend project and I did not want to waste much time making custom controls. The sliders are jQuery's UI sliders and as such not particularly well suited for what this should do. Might spend some time replacing this with something better.

As of why it would fully crash chrome I'm not sure. Maybe it runs out of memory? I think it wants about 80MB with DOM and everything and builds that out of 3MB of payload (which is about 20MB more than the google search page).

//EDIT: code is also on github under a BSD license in case someone wants to work on it: https://github.com/mitsuhiko/timesched

> Not many languages manage to implement map in a way that ["1", "2", "3"].map(parseInt) would result in [1, NaN, NaN]

It may seem counterintuitive at first, but it makes sense when you consider the function signatures. The map function passes two arguments; the element, and its index. The index ends up being used as the radix, which causes this sequence of calls:

  parseInt("1", 0);
  parseInt("2", 1);
  parseInt("3", 2);
I'd recommend creating a higher-order function that takes a function and returns a unary version:

  function unary(fn) {
    return function(arg) {
      return fn(arg);
    };
  }
Then you could use it like this:

  ["1", "2", "3"].map(unary(parseInt));
  // => [1, 2, 3]
I think the problem is that you assumed (not unreasonably) that [...].map(parseInt) was an eta reduction of [...].map(function(e) {return parseInt(e);}). Unfortunately it's not, which caused some unexpected results. This would happen in any language where the map function passes two arguments and the string-to-integer function has an optional second argument.

Consider the following Ruby (this is a really weird way to do it in Ruby, but I'm trying to make the method signatures match):

  # This lambda has the same type signature as JavaScript's parseInt
  parse_int = ->(str, radix = 10) { str.to_i radix }

  # This converts the lambda to a block and calls it with each element
  # from the array, along with its index.
  %w[1 2 3].map.with_index &parse_int
  # => ArgumentError: invalid radix 1
As an aside, I'm a recovering JavaScript hater as well. I've mostly made peace with JS, though there are still parts of the language that make my skin crawl (See this gist for my favorite example: https://gist.github.com/actsasbuffoon/7323667). That said, there are some parts of JavaScript that are genuinely great. I recommend reading JavaScript Allongé by Reginald Braithwaite. I'm scarcely exaggerating when I say the book completely changed the way I look at JavaScript.
I don't know a single language where the standard map function passes two arguments instead of one. Python has the starmap function as an alternative in case someone really needs that.
.net's .Select() method has both variants.
I agree that it's probably a bit unusual, and likely owes to the fact that all JS functions are variadic and ignore arity mismatches. Ruby's procs behave the same way, though its methods and lambdas are more traditional.
While I echo and amplify the disdain that Ronacher had for the code he cited in his article, I note that sarcasm doesn't work well online. There is of course nothing "cute" or "clever" about the sort of coding he showed. It is obviously very ugly and foolish, and I would've preferred the author be a bit more direct about this.

I think I'm sensitive to the inappropriateness of the words "cute" and "clever" regarding so much Javascript in the wild because of the decades I spent writing C++ in production environments. While I plodded through my share of big balls of mud, the ideal was always to produce code that was clear, maintainable, and extensible. Always think about the next coder down the line to look at your work, because that coder may be you; in six months time, what you wrote today may be almost completely unfamiliar to you.

I'm not seeing much of that sentiment in Javascript now. For the most part it seems to be written by a series of lone cowboys -- or rather, "ninja" -- who haven't considered that someone may one day need to do something else with their code.

Sometimes this is the result of laziness and amateurism, but I suspect that occasionally there are Javascript developers whose work truly qualifies as "cute" and "clever," or perhaps "too cute" and "too clever."

For instance, while I have a great deal of respect for John Resig of JQuery fame, I was mildly horrified by his book "Secrets of the Javascript Ninja." His code examples were undeniably clever, and demonstrated the profound understanding of Javascript that you'd expect. They would, however, often render production code nearly undecipherable and extremely difficult to debug at the very least. And of course there were always simpler, clearer ways to accomplish what he had done with "ninja" tricks.

So, to summarize, this article really just seemed to demonstrate ugly, foolish Javascript, whereas too cute, too clever Javascript is indeed a serious hazard.

>"For this project I obviously used jQuery which is impossible to avoid (and why would you) but also AngularJS with a bunch of UI components (angular-ui and some bindings to jQuery UI)"

Lol. Is this author trolling us? I don't know anybody at Google who uses jQuery, and Angular makes it particularly easy to avoid.

Cute and clever indeed!

The typeahead.js library should use a binary search of a sorted string array. A trie of string prefixes would be more elegant, but it would probably have worse data locality and heap fragmentation.

And instead of searching the entire database for every new prefix (e.g. "s", "sa", "san", "san f"), the API could return a stateful query object that could be more efficiently refined.