Array.prototype.toObjectByProperty( element=>element.property )

Jordan Harband ljharb at gmail.com
Thu Aug 10 08:03:29 UTC 2017


"Generic" can't apply when constructing an object, since you always need
pairs of a key and a value - so it doesn't need to be generic; it needs to
fit the use case.

Yes, I've had many a need for "fromEntries" or similar, which I've usually
achieved with a reduce. I've never once needed to create an object from an
iterable of "not entries". Needless to say, "use cases" are subjective.

`new Map` accepts an iterable of entries - that's the established pattern
that any new additions would almost certainly use.

On Thu, Aug 10, 2017 at 12:47 AM, Naveen Chawla <naveen.chwl at gmail.com>
wrote:

> `fromEntries` is much less generic than `fromIterable` (since not every
> iterable is an entries, but every entries is an iterable) and is much more
> verbose to use in the use cases we have just discussed. I have faced such
> cases often, but have NEVER faced a need for a `fromEntries`. Have you?
> Even if so, I've shown how `fromEntries` functionality can be achieved via
> `fromIterable` without any additional method calls, which is not the case
> vice versa
>
> On Thu, 10 Aug 2017, 3:26 a.m. Jordan Harband, <ljharb at gmail.com> wrote:
>
>> Naveen:
>> `Object.fromIterable(recentCountryNames, countryName=>countryName,
>> countryName=>countriesByName[countryName])`
>>
>> could also be:
>>
>> `Object.fromEntries(Array.from(recentCountryNames, countryName =>
>> ([countryName, countriesByName[countryName]])))`, without needing a
>> potentially confusing "keyCallback, entryCallback" API nor without builtins
>> needing to invoke user-supplied functions.
>>
>>
>> TJ:
>> I'm confused, can you provide a code sample?
>>
>> On Wed, Aug 9, 2017 at 2:08 AM, Naveen Chawla <naveen.chwl at gmail.com>
>> wrote:
>>
>>> Hi Jordan, great question.
>>>
>>> An iterable of anything!
>>>
>>> This is the signature:
>>>
>>> ```
>>> Object.fromIterable(iterable, keyFromElement[, valueFromElement])
>>> ```
>>>
>>> Examples follow:
>>>
>>> Supposing you had an array:
>>>
>>> ```
>>> [
>>>     {
>>>         countryName: 'UK',
>>>         population: 65640000
>>>     },
>>>     {
>>>         countryName: 'USA',
>>>         population: 323100000
>>>     },
>>>     {
>>>         countryName: 'Denmark',
>>>         population: 5731000
>>>     }
>>> ]
>>> ```
>>> ...and you wanted to cache the items by country name for quick access,
>>> to get:
>>>
>>> ```
>>> {
>>>     UK: {
>>>         countryName: 'UK',
>>>         population: 65640000
>>>     },
>>>     USA: {
>>>         countryName: 'USA',
>>>         population: 323100000
>>>     },
>>>     Denmark: {
>>>         countryName: 'Denmark',
>>>         population: 5731000
>>>     }
>>> }
>>> ```
>>>
>>> ...you would simply do
>>>
>>> ```
>>> const countriesByName = Object.fromIterable(countries,
>>> country=>country.countryName);
>>> ```
>>>
>>> to get that result. (the 2nd parameter defaults to return the iterated
>>> value if not provided).
>>>
>>> As callbacks, the `keyFromElement` and `valueFromElement` parameters
>>> allow you to supply anything you like to transform from the iterated
>>> element (or from elsewhere) into the keys and values you want:
>>>
>>> e.g. if you had an array of strings called "recentCountryNames" with
>>> `['UK', 'Denmark']`:
>>>
>>> ```
>>> const recentCountryDetailsByName = Object.fromIterable(recentCountryNames,
>>> countryName=>countryName, countryName=>countriesByName[countryName])
>>> ```
>>>
>>> would produce:
>>>
>>> ```
>>> {
>>>     UK: {
>>>         countryName: 'UK',
>>>         population: 65640000
>>>     },
>>>     Denmark: {
>>>         countryName: 'Denmark',
>>>         population: 5731000
>>>     }
>>> }
>>> ```
>>>
>>> As an aside, it can easily transform entries as follows:
>>> `Object.fromIterable(entries, entry=>entry[0], entry=>entry[1])` (if the
>>> entry "keys" happen to be valid object keys, otherwise you can simply
>>> provide a different transformation for the `keyFromElement` callback) but
>>> works equally well with all types of iterables
>>>
>>> On Wed, 9 Aug 2017 at 13:55 Jordan Harband <ljharb at gmail.com> wrote:
>>>
>>>> I think you're misunderstanding; the function would of course take an
>>>> iterable. However, an iterable of what?
>>>>
>>>> If it's an iterable of objects, then what's the key and what's the
>>>> value? What if it's an iterable of strings?
>>>>
>>>> The only thing that makes sense is if it's an iterable that provides
>>>> both a key and a value - and "entries" is the idiomatic structure in the
>>>> language to respect a list of key/value pairs (besides "an object", of
>>>> course).
>>>>
>>>> What would you suggest?
>>>>
>>>> On Wed, Aug 9, 2017 at 1:08 AM, Naveen Chawla <naveen.chwl at gmail.com>
>>>> wrote:
>>>>
>>>>> It is more generic than `fromEntries`
>>>>>
>>>>> On Wed, 9 Aug 2017 at 13:32 Naveen Chawla <naveen.chwl at gmail.com>
>>>>> wrote:
>>>>>
>>>>>> Iterable to object via `Object.fromIterable`
>>>>>>
>>>>>> On Wed, 9 Aug 2017 at 13:31 Jordan Harband <ljharb at gmail.com> wrote:
>>>>>>
>>>>>>> JS doesn't have interfaces (yet, tho there's a proposal) and
>>>>>>> regardless, the "interface" for "iterable" is "it has Symbol.iterator,
>>>>>>> nothing more".
>>>>>>>
>>>>>>> The only place a method like this - that produces an object - could
>>>>>>> possibly exist, is a static method on Object.
>>>>>>>
>>>>>>> I've already outlined two existing methods to copy one object's
>>>>>>> entries to another; the only new functionality would be "creating an object
>>>>>>> from entries", hence Object.fromEntries or similar.
>>>>>>>
>>>>>>> I still haven't seen any use cases that aren't covered by the
>>>>>>> existing "copy one object to another", or by a possible "entries to object"
>>>>>>> - does anyone have any?
>>>>>>>
>>>>>>> On Wed, Aug 9, 2017 at 12:56 AM, Naveen Chawla <
>>>>>>> naveen.chwl at gmail.com> wrote:
>>>>>>>
>>>>>>>> But I accept that this a very tall order for ES
>>>>>>>>
>>>>>>>> On Wed, 9 Aug 2017 at 13:22 Naveen Chawla <naveen.chwl at gmail.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Java has a great example of such a construct: default interface
>>>>>>>>> methods
>>>>>>>>>
>>>>>>>>> On Wed, 9 Aug 2017 at 13:21 Naveen Chawla <naveen.chwl at gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> The `toObject` behaviour doesn't need to be "implemented" on a
>>>>>>>>>> per-iterable class basis. It has a constant behaviour: iterate and on each
>>>>>>>>>> next(), pass the value to the `toKeyFromElement` and `toValueFromElement`
>>>>>>>>>> callbacks to generate and return an object. There must be some construct by
>>>>>>>>>> which that can be achieved. I wouldn't call it "better" to put it on Object
>>>>>>>>>> (for the reasons stated), but rather a compromise in the absence of any
>>>>>>>>>> such construct
>>>>>>>>>>
>>>>>>>>>> On Wed, 9 Aug 2017 at 13:12 T.J. Crowder <
>>>>>>>>>> tj.crowder at farsightsoftware.com> wrote:
>>>>>>>>>>
>>>>>>>>>>> On Wed, Aug 9, 2017 at 8:35 AM, Naveen Chawla <
>>>>>>>>>>> naveen.chwl at gmail.com> wrote:
>>>>>>>>>>> >
>>>>>>>>>>> > It would be in the `iteratable` `protocol` (interface)
>>>>>>>>>>>
>>>>>>>>>>> As Jordan said, that's likely to be a nonstarter. The Iterable
>>>>>>>>>>> protocol is *very* lean (exactly one required property) for a reason: So it
>>>>>>>>>>> can be supported with minimum investment. Much better, IMHO, to put
>>>>>>>>>>> functions on `Object` and `Map` (which is why that's what I suggested).
>>>>>>>>>>>
>>>>>>>>>>> -- T.J. Crowder
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>
>>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170810/69375b6f/attachment.html>


More information about the es-discuss mailing list