proposal-built-in-modules icon indicating copy to clipboard operation
proposal-built-in-modules copied to clipboard

Add remaining underscore / lodash features

Open mikemaccana opened this issue 6 years ago • 14 comments

Some points:

  • Standards succeed where they pave existing cowpaths. lodash is the most depended upon npm package.

  • Standards succeed when there are multiple independent implentations. There are already two implementations of underscore / lodash. Underscore is also quite popular.

  • While many of _ features are in ES8, a bunch - like .get() for getting a deeply nested key in an object - are not. For example, pretty much everyone who has to get some data from JSON needs to (safely, ie not failing if onee of the keys doesn't exist) get a deeply nested key in an object.

TC39 should implement the features from lodash andd underscore that do not already have ES equivalents.

mikemaccana avatar Dec 19 '18 15:12 mikemaccana

We're working on optional chaining, which I think should handle use cases of _.get() when the path string is fixed. Can we continue this discussion in that repository?

littledan avatar Dec 19 '18 16:12 littledan

Please consider providing something equivalent to underscore's omit. I find myself reaching for this all the time.

realtaraharris avatar Dec 20 '18 02:12 realtaraharris

Omit can be emulated using object destructuring:

> let a = { foo: 5, bar: 6, baz: 7 }
undefined
> a
{ foo: 5, bar: 6, baz: 7 }
> let { bar, ...noBar } = a
undefined
> noBar
{ foo: 5, baz: 7 }

Timer avatar Dec 20 '18 05:12 Timer

@littledan optional chaining sounds great, and yes any specific _.get()-specific discussion should be handled there. 👍

This issue is to enumerate the features from these commonly used libraries that do not currently have an ESnext equivalent - it's more than just a single feature. So yes let's please leave this open and find out what else is missing!

mikemaccana avatar Dec 20 '18 12:12 mikemaccana

It's weird because I recommended this, and it was closed as off topic and I was called disruptive

The next day Dan asked for this in public and now it's a good idea

There's a whole lot down there

https://github.com/tc39/proposal-javascript-standard-library/issues/39

StoneCypher avatar Dec 20 '18 17:12 StoneCypher

We really should pick up our basic functional predicates. Much of what lodash and ramda actually are are that.

The best place to look would be in the standard library of a very old functional language, like lisp, or a very active modern one, like clojure, because this is their bread and butter

It would be better to look at ramda than lodash. Underscore got a lot of its critical basics wrong in important ways

StoneCypher avatar Dec 20 '18 17:12 StoneCypher

Most important would be having a language-level deep copy

There are a bunch of really complicated decisions involved in deep copy, like what to do about cycles, how to handle classes with valueOf, et cetera

You can't really have a library deep copy, because it'll end up making a bunch of those decisions and not talking about them. Changing them, with time, the way jquery and underscore's keep doing.

Some of those decisions actually need access to the underlying jsvm

Take any two library implementations of deep copy and put them up to a stochastic tester like jsverify.

I've tested almost 50 of them at this point. I haven't found two that are compatible yet, except the ones that copy and paste one another.

The language needs a fundamental deep copy, so that downstream users can make adjustments to the deep copy that's present when the choices made don't fit needs.

StoneCypher avatar Dec 20 '18 17:12 StoneCypher

@Timer using destruct we'll generate unused variables (such as bar in your example). I suggest add a specific utility for omit, that will return exactly what you need, without creating unused stuffs.

renatoagds avatar Dec 21 '18 11:12 renatoagds

@renatoagds You could also write it like this:

let a = { foo: 5, bar: 6, baz: 7 };
let { bar: _, ...noBar } = a;

kasperpeulen avatar Dec 21 '18 14:12 kasperpeulen

Another option:

let a = { foo: 5, bar: 6, baz: 7 };
var noBar = Object.assign(
    ...Object.entries(a)
        .filter(([key, value]) => key !== 'foo')
        .map(([key, value]) => ({ [key]: value }))
);

If we would have something like a Object.from we could simplify that to:

let a = { foo: 5, bar: 6, baz: 7 };
var noBar = Object.from(Object.entries(a).filter(([key, value]) => key !== 'foo'));

kasperpeulen avatar Dec 21 '18 14:12 kasperpeulen

Regarding Object.from, there's Object.fromEntries which is close to stage 4.

lazarljubenovic avatar Dec 21 '18 15:12 lazarljubenovic

@kasperpeulen I know that we can do in a lot of ways, but that's exactly what lodash does. The exactly topic here is put this boilerplate inside the stdr library.

renatoagds avatar Dec 21 '18 17:12 renatoagds

@jdalton you've got some pretty unique insight here - any thoughts?

mikemaccana avatar Dec 24 '18 01:12 mikemaccana

Thanks for the ping @mikemaccana! I've been following this thread at a distance.

I believe the goal of this proposal is to define a mechanism for providing a more extensive standard library in JavaScript and not really about the specific methods that compose the various standard modules. We have a proposal process that folks can follow and bring to the attention of TC39 delegates like myself.

At the top of my wish list of things to be added to the language would be nicer ways to deep clone and deep compare (think Node's util.isDeepStrictEqual) values.

jdalton avatar Dec 24 '18 05:12 jdalton