3 ms·
Being a Ruby developer for quite a while, Underscore.js always struck me as an attempt to bring some of the native functionality of Ruby into the language that
by snitko 12y ago
Being a Ruby developer for quite a while, Underscore.js always struck me as an attempt to bring some of the native functionality of Ruby into the language that had none of it. Internal iterators being the most immediate example.
Problem is that Javascript lacks a lot of the things programmers need at hand. So they write stuff to complement that deficiency. I write in Dart as well and can tell you I love it precisely because it provides better OO capabilities through its core.
Which really brings a very important question to the table: what should be a part of the language and what shouldn't. A Unix minimalist in me wants a language to be as small as possible. But then when you actually start writing code, you mostly want simple things done without having to import new libraries.
- Suor 12y agoIf core is small then such language should provide a way to extend it outside. Like macros.
- andylei 12y agoor libraries... like underscore...
- mmahemoff 12y agoIt's not a coincidence that Underscore looks like Ruby, its creator has a Ruby background and similarly developed CoffeeScript along those lines. (Both of which are perfect for me as someone who uses Rails on the back-end.) Yes, JavaScript never had anything resembling a decent utils library, so an elegant and popular implementation like underscore was heaven when it arrived. It's the usual problem of browsers evolving too slowly and fragmenting too much for something like Java's collections to emerge as a standard. The situation has gotten better now, with even IE moving towards auto-upgrade, but it's still not feasible for JS core to ship with large, frequently-updated, JS libs. The closest thing is Node's standard library, but that's not going to be ubiquitous in browser's anytime soon. "what should be a part of the language and what shouldn't" In the absence of a standard library, you end up with a dozen competing libraries trying to fill the void, and that stifles end-user applications. We saw that a few years ago with the DOM. For the first ~8 years of JS, there was no significant DOM library, so app developers had to suck up the unfriendly raw DOM API. Then the toolkits started to emerge, giving way to huge fragmentation between jQuery, Prototype, MooTools, Dojo, and YUI. Suddenly libraries were jQuery plugins or MooTools plugins and your app was using the jQuery stack or MooTools stack. So the next 8 years of JS saw vast effort duplicated as developers built parallel libraries for each toolkit. So I think the answer is to launch a language without the kitchen sink, but watch the community and gradually standardise useful functionality as the need emerges and adapt popular open source libraries as they becomes popular. Java did this well in its heyday. In JS's case, a lot of the DOM conveniences are now becoming core JS, but the nature of JS means libraries move slower than other languages.
- snitko 12y agoYou made a perfect case for Dart.
- rnbwd 12y ago>the nature of JS means libraries move slower than other languages. prior to node and npm maybe. The JS npm ecosystem is actually growing faster than any other language's module/library system, it's on the cusp of becoming #1 in the world. http://modulecounts.com/ http://modulecounts.com/
- spankalee 12y agoI maintain a utility library for Dart called Quiver, that you could view in the same vein as Underscore, or Guava. Like you mention, the Dart core libraries are pretty rich, so Quiver doesn't have to define as many fundamental concepts. But rather than there being a sprawling library, many of the nice things come about from composing a couple of features. My favorite example is Iterable. Dart's Iterable interface doesn't just have .iterator, it has .forEach(), .map(), .where(), .reduce(), .take(), .first, .last... 27 methods and getters! This makes using Iterables a consistent pleasure, but it could be a heavy burden on Iterable implementors, except that Dart has mixins and the IterableMixin, so all you need to do to implement the 27 methods is implement .iterator and use the mixin, which uses .iterator to implement everything else. The ubiquity of Futures and Streams and how dart:html uses them consistently instead of raw callbacks is another example. There are other Iterable utilities that are possible, which is where one of Quiver's libraries steps in to provide things like zip(), enumerate() and partition(), which does raise the same question you ask: why are the built-ins special, where do you draw the line? That's a judgement call where I tend to fall on a pretty pragmatic side of things. Programmers benefit from consistency - not just because there's one way to learn how to do things, but also because some powerful idioms, like more functional-style programming, become popular in a vicious cycle: as they become more common, more people learn them and they become even more common. Having some of the higher-level bits ship with the platform makes everyone's life easier. quiver: http://pub.dartlang.org/packages/quiver http://pub.dartlang.org/packages/quiver