-
Notifications
You must be signed in to change notification settings - Fork 20
.fromEntries
vs .from
#7
Comments
Has that proposal been presented to the committee yet? |
I wrote about the name question a bit here: https://github.com/bathos/object-from-entries#method-name
I don’t have a strong opinion on this. I thought 'fromEntries' seemed more intuitive in light of |
I should also add that I haven’t done any research on whether there’s non-clobbering |
I think that it should be sync. cc @leobalter @allenwb |
I could go either way on this question. On the one hand, all of My tentative vote is to stick with |
FWIW I think If we had that, like we have a proper definition of an iterator, we could consider exact same modern approach through a generic EntriesAn iterable collection of key/value pairs PairAn array of length 2 with any key at index 0 and any value at index 1. Symbol.entriesA method that returns entries. Same as we recently put Object.defineProperty(
Object.prototype,
Symbol.entries,
{
configurable: true,
value() {
return Reflect.ownKeys(this)
.filter(k => this.propertyIsEnumerable(k))
.map(k => [k, this[k]]);
}
}
); Object.from(generic)A method that checks Object.defineProperty(
Object,
'from',
{
configurable: true,
value(generic) {
if (Symbol.entries in generic) {
return generic[Symbol.entries]()
.reduce((o, e) => ((o[e[0]] = e[1]), o), {});
} else {
return {};
}
}
}
); ApplicationsWhenever a class has In case of RationaleUsing a special My 2 cents. |
@WebReflection I don’t understand the examples given —
According to that logic, while Object.fromEntries(Object.entries({ a: true, b: false }));
// gives us { '0': [ 'a', true ], '1': [ 'b', false ] } It doesn’t seem to solve the same set of problems as the proposed behavior. |
@WebReflection interesting idea; we could modify it a bit by not installing a default implementation on Object.prototype, but instead using that implementation when Symbol.entries wasn't present. One catch would be that Map/Set/Array @bathos I think the suggestion is that you wouldn't call The downside here, though, is that the common case is when you want to transform one list of entries to another - which would be relatively awkward with @WebReflection's suggestion. |
Right. I’m not clear on what the utility would be — @WebReflection can you explain more about what you see the use cases as? Does it address the common case and I’m not spotting it? |
@bathos I've overly simplified with the generic notion that if there's entries then it's OK to use it 'cause in the Array case it won't be OK but the Example, if the returned array The proposal is that The
that would use
I've forgotten about it, here it is, same as Object.defineProperty(
Object,
'from',
{
configurable: true,
value(generic, transform = (v, k) => v) {
if (Symbol.entries in generic) {
return generic[Symbol.entries]()
.reduce((o, e) => (o[e[0]] = transform(e[1], e[0]), o), {});
} else {
return {};
}
}
}
); |
P.S. like I've said, if we had an However, when it comes to composition, Object.defineProperty(
Array.prototype,
Symbol.entries,
{
configurable: true,
value() {
for (const pair of this) {
if (!Array.isArray(pair) || pair.length !== 2)
throw new TypeError('invalid pair');
}
return this;
}
}
); That special method would make every returned edit as counter idea there could be this specialised class and an class Entries extends Array {
[Symbol.iterator]() {
const out = [];
for (const pair of this) {
if (!Array.isArray(pair) || pair.length !== 2)
throw new TypeError('invalid pair');
else
out.push(pair);
}
return out;
}
} That would be used as return value of |
I appreciate the concept and wiser folks may see good reasons to take the well-known symbol approach. My sense personally is that it seems perhaps overbaked — the complexity and reach doesn’t seem justified by the problem space. Perhaps I’m defining the problem space too narrowly though, not sure. Regarding a definition for Entries, it may be relevant that the existing consumer of entries, Map, uses a contract which is "an iterable of objects". It accesses the "0" and "1" properties of each object, so you could further say "an iterable of objects on which "0" and "1" properties may be accessed", though it does not care whether they have been defined. If the definition were formalized to be "an array of length 2 with any key at index 0 and any value at index 1", Map would become a sort of exception in terms of its permissiveness. I don’t know if this would matter or not. |
@bathos while I understand your point of seeing it as overbaked, I find Imagine a DOM node with a state represented by its Imagine a Blob that could expose, though I see
Blocking it at |
I should clarify that
is what the intention was — nothing earth-shattering haha. A number of static utility methods exist just to make common patterns more expressive and direct. For example, Object.getOwnPropertyDescriptors could be implemented by combining other methods and a reducer, too. (Or for that matter, Array.prototype.map and Array.prototype.filter can also both be implemented as reducers.) I think the ideas you’ve described are very interesting, especially with those last examples. I’m super intrigued but my reservation is that it seems quite removed from what this proposal was intended to cover. |
@bathos maybe we agree that having now Again, I'm OKihs with |
Yes, I’d agree (and perhaps the separation would also permit Array’s @@entries or similar from having to special case anything). I mentioned in the 'name' section that one reason Please feel free to keep exploring these ideas in the context of this proposal in any case — I had one thing in mind so I wanted to say so, but really it’s out of my hands now what direction it takes. I’m particularly curious to hear what @bakkot has to say. |
@WebReflection I don't really see the advantage of |
I don’t think an Object.from would ever make Object.fromEntries obsolete; creating a snapshot is typically done with toJSON, since snapshots typically need to be serializable. A generic way to provide entries might indeed make sense, but that current generic method is “an entries method that returns an iterator”. |
@WebReflection I find the idea of an I do think that it's probably out of scope for this proposal, mind; this proposal seems useful either way. An "entries" protocol would just make it easier for user code to play along. |
@Loirooriol what you say is basically: "wouldn't be the same if every object was iterable and returned entries?" to which I answer no. It's counter-semantic to write Let's keep the semantic |
|
Since this accepts arbitrary iterables and produces something which is not an array, there's no obvious place for a mapping function to go, which suggests the mapping function argument could be useful. On the other hand, I would strongly prefer standardizing some iterator adapters (in another proposal) and then expecting those to be used instead. The mapper argument is kinda dumb - wouldn't it be much clearer if we could write Object.fromEntries(map(fn, x)) rather than Object.fromEntries(x, fn) ? Then no one has to learn about this non-obvious second argument, and you could do more powerful things (like filter) to boot. (Where |
fwiw the Array.from mapper has turned out to be very useful, non-obvious or not. |
I’m also in favor of a distinct iterator utilities module for facilitating this (and more), but I don’t believe that having that plan really precludes the possibility of introducing a mapping arg here anyway. I lean slightly towards avoiding it for principle of least surprise reasons. It doesn’t seem super obvious that there would be a second arg or what it would do. I mentioned in #13 that "single arg functions play nicely with Array.prototype.map out of the box"; @ljharb pointed out that supporting that shouldn’t be a specific design motivation. That may be true; my angle was footgun avoidance, since I’ve encountered bugs caused by using >1 arity functions as iterator function callbacks enough times to want to avoid creating new opportunities for them to occur. However I agree this is a pretty weak argument for avoiding the mapping argument. |
#13 has been repurposed to cover a second argument as either a proto - like Object.create, or a mapper - like Array.from. It seems like Is it alright to close this, and leave |
I haven't any strict opinion about it, but already available proposal
.from
/.of
methods on collections. OnMap
/WeakMap
, it works with entries.The text was updated successfully, but these errors were encountered: