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"
      

Run codeHide result


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?

+3


source to share


3 answers


Constructor

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"
      

Run codeHide result





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"
      

Run codeHide result


+5


source


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 accepts Iterable

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.

+1


source


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"));
      

Run codeHide result


-2


source







All Articles