8 ms·
Destructuring and Recursion in ES6
- whichdan 12y agoconst description = (nameAndOccupation) => { const [[first, last], occupation] = nameAndOccupation; return `${first} is a ${occupation}`; } description([["Reginald", "Braithwaite"], "programmer"]) //=> "Reginald is a programmer" This is going to make code a lot more readable. I'm excited!
- ilkkao 12y agoMe too. I'm hoping that V8 starts to support destructuring soon (https://code.google.com/p/v8/issues/detail?id=811 https://code.google.com/p/v8/issues/detail?id=811) so I can optimize my io.js code.
- WebReflection 12y agoor does it? You are passing arrays of arrays with a potentially random index position based convention that makes no sense to me at first read. Is that how you pass on real-world code a generic person data around? Is that how you don't use i18n for string and how you ignore occupations that starts with vowels? Destructuring is nice as other new features in ES6 but abusing these just because there are there ... no, I don't think that's going to improve any code or any readability.
- bzbarsky 12y agoYou can destructure objects as well. So: const description = (nameAndOccupation) => { const { name: { first, last }, occupation } = nameAndOccupation; return `${first} is a ${occupation}`; } description({ name: { first: "Reginald", last: "Brathwaite" }, occupation: "programmer" }); And this last _is_ in fact how real-world code would pass person data around. Your i18n points stand, of course.
- marxama 12y agoThat's really nice. Is it possible to do the destructuring directly in the argument list?
- peferron 12y agoYes: const description = ({name: {first, last}, occupation}) => `${first} is a ${occupation}`; Edit: just noticed that `last` is not used, so we can remove it from the destructuring: const description = ({name: {first}, occupation}) => `${first} is a ${occupation}`;
- tracker1 12y agoIf you are passing JSON around, then arrays may be better for streams of data than json, with key/value ... if you are passing tabular data from one service to another, then you may very well pass an array you then want to destructure into an object. For that matter, maybe even messagepack, protocol buffers , etc over 0mq or direct sockets... although straight json + gzip is pretty effective.
- xamuel 12y agoHow is that more readable than: function describe(nameAndOccupation){ return `${nameAndOccuptation.name.first} is a ${nameAndOccupation.occupation}`; } ? When people use features purely for the sake of using those features, the result is not "more readable". Ever notice that pseudocode is almost always imperative?
- whichdan 12y agoI should have been a little more explicit: the string interpolation, though not the focus of the article, is part of what interests me w.r.t. readability.
- reconbot 12y agoIt's hard to believe this is javascript. I write that with a lot of love. These are some of my favorite language features but It's going to take some adjustment to be comfortable using and reading them in JS.
- netcraft 12y agoThe more I see and learn about ES6 the more I think JS code is going to look completely different in a couple years than it looks today - and in a good way.
- SimeVidas 12y agoWait till you see ES7 async and await :-D http://imgur.com/HvQbw48 http://imgur.com/HvQbw48
- kxo 12y agoWhich can be used today via 6to5!
- jordanlev 12y ago6to5 compiles ES7 too?
- Chris_Newton 12y agoSometimes, yes. :-) http://kangax.github.io/compat-table/es7/ http://kangax.github.io/compat-table/es7/
- eddyb 12y agoI had first seen async/await in traceur-compiler. I was using it with Node.js' fs module two years ago, I believe.
- Touche 12y agoHow do you return a result (this function isn't doing so)? I'm guessing getJSON could be returning a Promise but there must be a way to do the same in an async function. EDIT, here's the spec, looks like you can just return: https://github.com/lukehoban/ecmascript-asyncawait https://github.com/lukehoban/ecmascript-asyncawait
- iMark 12y agoES6 transpiling has been a bit of a revelation to me lately. Object destructuring is also exceedingly useful. On a bit of a tangent from the article, I'm interested by the use of const as the default for variable declaration. My background is such that I've always considered constants as things that are class level constants (thank you Java), but reading up on Swift has made me rethink this. Clearly const has the potential to reduce runtime errors. I'd appreciate it if anyone could recommend any further reading on the subject.
- acjohnson55 12y agoI'm not sure about the best possible resource to read, but in the traditional of functional programming, immutability is preferred in nearly all cases. This is particularly important when it comes to data with long-lived scope (e.g. members of objects, data within the scope of closures, etc.) because the functions that operate on non-constant data lose purity and become more difficult to reason about and test. In other words, mutability leads to side-effects, wherein operations on data in one part of a program are visible within other function, without explicitly being passed in. In many functional languages, mutation of variables is only allowed in special cases, and in some languages, it's not allowed at all. This can be weird if you learned programming in a tradition where modifying variables is one of the first things you were taught, but once you get used to not mutating your variables, the benefits really start to shine. As you mentioned, it often prevents entire categories of errors. For instance, I haven't written a for loop with an index variable in well over a year, in favor of using map/flatMap/filter/fold and friends, and for that reason, I can't remember my last fencepost error. Like I said, I don't know the best resource, but learning Scala was really influential for me in immutable programming, and the Functional Programming Principles in Scala Coursera course [1] and the (unrelated) Functional Programming in Scala book taught me a lot of what I know on the topic. [1] https://www.coursera.org/course/progfun https://www.coursera.org/course/progfun [2] http://manning.com/bjarnason/ http://manning.com/bjarnason/
- tel 12y agoDouble down on Rúnar's book! You have only learned half of Scala until the day that "FP in Scala" is trivial to you.
- taylodl 12y agoYet another validation of Greenspun's tenth rule. Now if only ES6 would get proper tail recursion then we'd be all set!
- ivank 12y agoI think these are in the spec. https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tail-position-calls https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ta...
- jessaustin 12y agoIn that case, I'm shocked that no Lispers have showed up to castigate raganwald for writing something like fn(first, foldWith(fn, terminalValue, rest)); With an accumulator foldWith could call itself directly! b^) Actually this indicates to me that ES6 should implement folds itself.
- janjongboom 12y agoAlso coming to ES6 is destructuring objects: function doSomething(aObj) { let { x, y } = aObj; } doSomething({ x: 1, y: 4 })
- drapper 12y agoDon't want to come off overly bitter, it's certainly interesting, but I'd like to see some practical uses of this, besides reimplementation of map() and other "low-level" functions...
- dukerutledge 12y agoHow about multi value return from functions. ``` x = foo(); oh = x[0]; no = x[1]; ``` vs ``` [oh, yeah] = foo() ```
- phpnode 12y agoobligatory mention that 6to5[0] lets you use all this stuff, and more, today. I've been using it for 3 months now and it has totally transformed the way I write JS applications, it's awesome. [0] https://6to5.org/ https://6to5.org/
- fenollp 12y agoSo basically pattern matching, shorter syntax for lambdas, string manipulation à la Ruby (but with backquotes, why?) and… confusing list with array EVERYWHERE in the language? No TCO? A `map` (sorry, `mapWith`) that creates then concatenates lists? 2015 sounds amazing!
- Chris_Newton 12y agoThat seems quite a negative view. The features mentioned in the article are only a small part of what is coming in ES6.[1] The “fat arrow” syntax for defining anonymous functions is much shorter and neater than the cumbersome notation we’ve had in the past: items.map(function (item) { return do_something_with(item) }) becomes items.map(item => do_something_with(item)) and there are both expression and statement variations of fat arrow functions, so we don’t need the return in this sort of situation either. There are also some other significant differences, particularly in what “this” means within the anonymous function. Combine that cleaner notation with the introduction of generators[2] and we can have lazy fluent interfaces for transforming data efficiently, along the lines of: items.map(item => item.interesting_property) .filter(item => is_wanted(item)) .reduce((item1, item2) => combine_usefully(item1, item2), initial_value) It’s not yet completely clear how we will take advantage of these possibilities in standardised ES6, because being backward compatible is a priority so you can’t just make sweeping changes like having all the existing Array.prototype functionality become lazy. This article[3] gives some ideas of how the kinds of utility library we’ve used in the past might look if they were written to take advantage of ES6’s new features, and presumably even if ES6 doesn’t include this kind of generator-based lazy functionality as standard it won’t take long before libraries are written to do it if they haven’t been already. Incidentally, that emphasis on backward compatibility also explains the use of back-ticks for strings with substitution. You need a new syntax that doesn’t change any existing behaviour, so regular single- and double-quoted strings can’t be used. There’s a lot more to ES6 besides just these areas. The article and this HN discussion are simply concentrating on some of the more interesting data-munging parts of it. For example, it also finally has a useful module system.[4] It really is quite a step up from today’s JavaScript in actual use; perhaps a good analogy would be the shift from Python 2 to Python 3, where the older version still does a decent job but a lot of little details are better in the newer one and the cumulative effect feels like a qualitative improvement in the language. [1] In practice, these features are already available today with only a small amount of effort, because you can use a transpiler like 6to5 or Traceur to convert ES6 code into ES5 that will run quite happily in any modern browser. These transpilers are straightforward to install and literally a one-liner to run, similar to installing SASS to convert an SCSS stylesheet to CSS for use in the browser. They are already integrated nicely with most other popular tools like Gulp, Grunt and Browserify. At worst you need a polyfill for a few features, but for example 6to5 provides one polyfill that does everything, so again this is a very simple thing to incorporate into your project if you do need it. [2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... [3] http://aaronstacy.com/writings/if-underscore-was-written-in-es6/ http://aaronstacy.com/writings/if-underscore-was-written-in-... [4] Very sensibly, the transpilers used to work with ES6 today can just turn those ES6 modules into AMD or CommonJS modules for compatibility with other existing tools. For example, you can use a 6to5 plug-in with Browserify, and it will convert ES6 modules into CommonJS ones that Browserify itself can then work with in the usual way. Again, this is yours for the price installing the plug-in using npm and an extra command-line option to Browserify, or something similarly straightforward using other package managers/build tools.
- eric_bullington 12y agoHah, I'm tempted to go through the Ocaml 99 problems (which was inspired by the Prolog version) using ES6 [1]. Turns out, with recursion and a head and tail function, you can do virtually anything with lists. I hope the popular JS engines optimize the hell out of the gathering operator, and adds TCO (it's on the ES6 spec, evidently). Then we won't even need to cross our fingers when we describe JS as a functional language to our peers. And with the increasing emphasis on immutability, as preached by the React crowd, with cross seeding from the Clojurescript-React connections, JS grows even closer to being a Scheme [2]. If ES7 would lock down 'use strict' mode against even more of JS's weak-typing bloopers, things would be even better yet. I don't see why they shouldn't. They whole reason for 'use strict' is to give people who need backwards compatibility an out. Incidentally, I'm also having great success using ES6 arrow functions at work, thanks to 6to5 [3]. I do a lot of d3 work, and arrow functions have made using d3, particularly the ubiquitous d3 accessor functions, so much nicer. Highly recommended. For the first time since Node, I'm actually getting excited about Javascript's prospects. Now, if only they'd add types, and sum types... 1. http://ocaml.org/learn/tutorials/99problems.html http://ocaml.org/learn/tutorials/99problems.html 2. No, I don't actually believe that JS is a Scheme in disguise. 3. https://github.com/6to5/6to5 https://github.com/6to5/6to5
- gsnedders 12y ago> If ES7 would lock down 'use strict' mode against even more of JS's weak-typing bloopers, things would be even better yet. I don't see why they shouldn't. They whole reason for 'use strict' is to give people who need backwards compatibility an out. Why we shouldn't? Because we (as in browser vendors) can't just break compatibility with all the websites that use strict mode today — that's a bad (/bad/) experience for our users, to have something they used every day in version x of our browser not work in version x+1. The "use strict" pragma won't ever be used for anything more than the ES5 strictness, and there's an increasing unwillingness to introduce further mode-switches. But never is a long time, and I think many of us would like to see something like TypeScript integrated into the language, and possibly introduce a strictly typed mode.
- eric_bullington 12y ago
- peferron 12y agoI've been pondering a few style questions recently: 1. When to use 'function' vs '=>'? Leaving aside hoisting and handling of 'this', 'function' and '=>' are usually interchangeable: function foo(x) { // do something } let foo = x => { // do something } I prefer to keep using 'function' because it's immediately obvious to the reader that we are creating a function. With '=>', the reader doesn't know if foo is a function or not until reaching '=>', which is located after the argument list. There's also almost no terseness gain. A potential win for '=>' though would be the ability to declare the function as 'const'. With closures, '=>' wins because the reader already expects a function, and the terseness gain is significant: somearray.map(function(x) { // do something }); somearray.map(x => { // do something }); 2. When to use {} around the function body? somearray.forEach(x => /* a single statement */); somearray.forEach(x => {/* a single statement */}); {} around the function body are optional if there's only a single statement. However, for clarity, I still use {} when I want to make it clear that we are not using the return value. I think that might be overkill though: the reader should aready expect that 'map', 'filter' and friends will use the return value, while 'forEach' will not. 3. 'let' or 'const'? This one is already mentioned in a sibling comment, so let's keep the discussion there. I realize that these are tiny style decisions that will probably incite endless bikeshedding, but I'm still interested in hearing opinions from fellow HNers. :)
- jarcane 12y agoHaskell possesses similar syntax, save that one must prefix an anonymous function with \, like so: \x -> x * 42 It's possible as well to use it bare like that, but only in very particular places, so it's generally much clearer to use it wrapped in parens: (\x -> x * 42) Perhaps some similar convention would make it clearer where a lambda is being used in .js?
- lewisl9029 12y agoI wish named arrow functions could make it into the spec, but until then, I'll personally stick with the full, named function declaration for all of my functions because it makes stack traces much more readable, which far outvalues the saved keystrokes that arrow functions provide when building non-trivial applications.
- philsnow 12y agoI've never liked this corner of JS, and haven't kept up on ES6 or any of the modern dialects of JS, but it looks like `undefined` is still hanging around as a first-class thing? const length = ([first, ...rest]) => first === undefined ? 0 : 1 + length(rest); Having worked in languages that support multiple (destructuring or not) function definitions, this doesn't look quite right. Here's something I typed into chrome's JS console: > [1,2,3].length 3 > [undefined, 2, 3].length 3 Wouldn't the above-defined ES6 `length` function return 0 for the latter array? To mock up a similar syntax that would handle this more gracefully (and more sensically): const length = case ([]) => 0, ([first, ...rest]) => 1 + length(rest); Wouldn't it be better in general to be able to destructure arguments using syntax? If you can't use a case-like syntax for this, what do you do to be able to handle different structures?
- peferron 12y agoYes, the ES6 `length` function would return 0 for [undefined, 2, 3]. I hope it was only used as an example in the article and nobody is planning to really use this. (Edit: see sibling comment; the article is already aware of this issue.) And yes, ES6 pattern matching is still quite limited.
- picks_at_nits 12y agoFrom the footnote: "Well, actually, this does not work for arrays that contain undefined as a value, but we are not going to see that in our examples. A more robust implementation would be (array) => array.length === 0, but we are doing backflips to keep this within a very small and contrived playground.” http://raganwald.com/2015/02/02/destructuring.html#fn:wellactually http://raganwald.com/2015/02/02/destructuring.html#fn:wellac...
- philsnow 12y agoah, thanks for pointing that out, I came here and ctrl+f'ed for 'undefined' but did not do the same in the article.
- noobermin 12y agoCompletely unrelated, but even assuming the author of the article posts here, are you from Columbus OH? I've gone to One-Line Coffee (the source of the first pic) myself a number of times!