Why doesn't it accept a map constructor Array from iterable tuples?
I created a set type in Javascript that implements the protocol Iterable
. It is now easy to convert to Map
:
const Tuple = (...args) => {
const Tuple = f => f(...args);
Tuple[Symbol.iterator] = () => args[Symbol.iterator]();
return Tuple;
};
new Map([Tuple(1, "a"), Tuple(2, "b")]); // Map {undefined => undefined}
Instead, I have to do the conversion manually:
const Tuple = (...args) => {
const Tuple = f => f(...args);
Tuple[Symbol.iterator] = () => args[Symbol.iterator]();
return Tuple;
};
const toArray = tx => tx((...args) => args);
const Map_ = (...pairs) => {
return new Map(pairs.map(pair => toArray(pair)));
};
const map = Map_(Tuple(1, "a"), Tuple(2, "b"));
console.log(map.get(1), map.get(2)); // "a" "b"
Seems to Map
only accept Iterable
for outer composite type, not inner pairs. What am I missing? Is there another way to get the conversion?
source to share
Map
is defined as accepting any Iterable key / value objects, where key / value objects are defined as objects, where property 0
is the key and property 1
is the value. It doesn't say anything about resolving Iterables for key / value objects. (It might have been great if it would allow them and determine that it will name the iterator exactly twice, but ... that's not what they did. :-) And it would be more difficult ...)
If we look at the spec , yours Tuple
will work if it supports properties 0
(for key) and 1
(for value). For example:
// (Defined this way because you seemed to want a non-constructor)
const TupleMethods = {
get "0"() {
return this.key;
},
get "1"() {
return this.value;
}
};
const Tuple = (key, value) => {
const t = Object.create(TupleMethods);
t.key = key;
t.value = value;
return t;
}
// Usage:
const m = new Map([
Tuple("one", "uno"),
Tuple("two", "due"),
Tuple("three", "tre")
]);
console.log(m.get("two")); // "due"
In the comment, you mentioned immutability. Maybe:
// (Defined this way because you seemed to want a non-constructor)
const TupleMethods = {};
Object.defineProperties(TupleMethods, {
"0": {
get() {
return this.key;
}
},
"1": {
get() {
return this.value;
}
}
});
const Tuple = (key, value) => {
const t = Object.create(TupleMethods);
Object.defineProperties(t, {
key: {
value: key
},
value: {
value: value
}
});
return t;
};
// Usage:
const m = new Map([
Tuple("one", "uno"),
Tuple("two", "due"),
Tuple("three", "tre")
]);
console.log(m.get("two")); // "due"
source to share
I have created a type of code in Javascript that implements the protocol
Iterable
.
not to do. Tuples have the distinct property that they are of a fixed length and each element has (can have) its own type, whereas (iterable) collections are made up of multiple elements of the same type. Of course JavaScript doesn't care about types (all arrays are heterogeneous), but you, as a programmer, should.
Why
Map
only acceptsIterable
for outer composite type and not inner pairs?
For the same reason. The elements are pairs or two tuples represented as arrays (due to the lack of another data structure and the simplicity of not entering them the way they did for the results of an iterator). They always have exactly two elements available like [0]
and [1]
(they don't even need it .length
!) And there is absolutely no reason to repeat them.
source to share
const Tuple = (...args) => Object.entries({[args.shift()]: args.shift()});
const map = new Map(Tuple(0, "a").concat(Tuple(1, "b")));
console.log(map.get("0"), map.get("1"));
source to share