Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Idx: Easily access deeply nested nullable fields in JavaScript (facebook.github.io)
42 points by anp on March 13, 2017 | hide | past | favorite | 19 comments


As much as Coffeescript gets maligned, its best feature (that hasn't been replicated, not even here) was the existential operator:

  friends = user?.friends?[0]?.friends
It would even work properly with functions:

  friends = getFriends?()
Which compiles to:

  friends = typeof getFriends === "function" ? getFriends() : void 0;
`idx` is not quite the existential operator, but it seems cleaner then `_.get`'s string representation of your path.


The existential operator has been introduced as an ECMAScript proposal[1], so it will probably be included in future versions of JavaScript. The `idx` function is just a temporary workaround.

When it gets added to the language, we can codemod away all usage of `idx` to use the question-mark syntax.

[1] https://github.com/claudepache/es-optional-chaining


FWIW, the existential operator is not unique to CoffeeScript, e.g. I'm fairly certain Cobra had it before CoffeeScript was created.


I don't quite get this, maybe someone can help. There's already a proposal for adding the existential operator in ECMAScript, if you're going to require babel transpilation why not simply write a babel plugin for the existential operator and use that?

If the argument is "because the proposal is immature and could be withdrawn" then the counter argument is that you have basically extended the language already by providing a built in "idx" global much like, say, parseFloat, with the difference that your function does not have any chance of actually being in the spec at any point, unlike the existential operator, thus you're basically masquerading the fact that using idx and the current proposal is the exact same thing just with different syntax.


At Facebook, we use Flow for type safety. We didn't want to have to introduce support for the existential operator until all of the details were more finalized.

Until then, we needed to have something that required minimal work (e.g. changes to the parser) that could tie us over until the language had proper support.

Also, we've been using this before the existential operator was formally proposed. (I should've probably got off my lazy butt to publish this sooner, but oh well.)

The plan is indeed to codemod this to the existential operator when it becomes available.


I haven't heard of this either. I guess they just wanted something that worked with minimal effort. Making the plugin and writing/coming up with spec tests takes time but albeit a better effort for the community overall. Maybe we can get more contributors for this effort now?

I made an issue for parser support, and after that we can create a babel plugin though https://github.com/babel/babylon/issues/328.


Relevant discussion of the existential operator on ESDiscuss: https://esdiscuss.org/topic/existential-operator-null-propag...


As usual, coffeescript had it first.


For context, this is a special case of Haskell's monads, which was also adopted by languages like Swift.


Reminiscent of Clojure's get-in function as well. [1]

[1] https://clojuredocs.org/clojure.core/get-in


This is more like a clojure macro in that it runs via a compiler extension to avoid the runtime call overhead of something like get-in.

Seeing how verbose and painful it looks, it's also an interesting commentary on macros in JS.


I wonder if there are other useful monads that would be useful to add to JavaScript.


JavaScript already has monads, whether or not they are recognized as such. What JavaScript needs is either Haskell's syntactic sugar for monads, or, much much better, lisp-style (as opposed to cpp or m4) macros which can be used to implement that sugar directly. The macros could even be run during a one-time "compile" step on the server before being served; or not, if the cost of expanding them is less than the cost of sending expanded code over the network.


How does this differ from lodash's get method?


- Flow understands the semantics of it.

- The path can only be given as a static function literal and there is no function call overhead at runtime because of the bundled babel transform that transforms the code to a bunch of ternary operators.


Is the FN call overhead really that horrible in lodash? I didn't see any side by side comps.

Also, the transformed code (like all transformed babel) is most likely ugly and more verbose than using lodash's get, no?


> Is the FN call overhead really that horrible in lodash?

The overall size overhead is what is horrible.

> Also, the transformed code (like all transformed babel) is most likely ugly and more verbose than using lodash's get, no?

Yes, but it also performs at what is probably as-close-to-optimal as possible. The resulting ternaries are extremely easy to work with for even the most basic of JS compilers. Source maps work well - I don't see this as a downside at all.


Naw, Lodash is modular. You can cherry-pick its modules. It's less than 716 bytes (with lodash-webpack-plugin).


The function call overhead is in browsers and in node, but it is low. Inlining is a top priority for all JavaScript implementations.

However, I wonder why lodash doesn't use a lambda. Parsing that path seems silly. It could just be a try on a lambda https://github.com/lodash/lodash/blob/master/.internal/baseG...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: