diff --git a/README.md b/README.md index 4f9e195..5565b64 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,15 @@ delete(key) get(key) ``` +```js +// Fetch the value from a Map located at the corresponding key. +// If the key is missing, the key is set to the result of function fun. +// key: * +// fun: Function () -> value +// returns: value +getOrCompute(key, fun) +``` + ```js // Set a value on the Map stored at the `key` location. // key: * diff --git a/src/ChainedMap.js b/src/ChainedMap.js index 00822de..7777415 100644 --- a/src/ChainedMap.js +++ b/src/ChainedMap.js @@ -72,6 +72,13 @@ module.exports = class extends Chainable { return this.store.get(key); } + getOrCompute(key, fun) { + if (!this.has(key)) { + this.set(key, fun()); + } + return this.get(key); + } + has(key) { return this.store.has(key); } diff --git a/src/Config.js b/src/Config.js index 487061b..f7f4505 100644 --- a/src/Config.js +++ b/src/Config.js @@ -95,19 +95,11 @@ module.exports = class extends ChainedMap { } entry(name) { - if (!this.entryPoints.has(name)) { - this.entryPoints.set(name, new ChainedSet(this)); - } - - return this.entryPoints.get(name); + return this.entryPoints.getOrCompute(name, () => new ChainedSet(this)); } plugin(name) { - if (!this.plugins.has(name)) { - this.plugins.set(name, new Plugin(this, name)); - } - - return this.plugins.get(name); + return this.plugins.getOrCompute(name, () => new Plugin(this, name)); } toConfig() { diff --git a/src/Module.js b/src/Module.js index 3f247a6..0199322 100644 --- a/src/Module.js +++ b/src/Module.js @@ -10,19 +10,11 @@ module.exports = class extends ChainedMap { } defaultRule(name) { - if (!this.defaultRules.has(name)) { - this.defaultRules.set(name, new Rule(this, name)); - } - - return this.defaultRules.get(name); + return this.defaultRules.getOrCompute(name, () => new Rule(this, name)); } rule(name) { - if (!this.rules.has(name)) { - this.rules.set(name, new Rule(this, name)); - } - - return this.rules.get(name); + return this.rules.getOrCompute(name, () => new Rule(this, name)); } toConfig() { diff --git a/src/Resolve.js b/src/Resolve.js index ed94243..dc1a5a1 100644 --- a/src/Resolve.js +++ b/src/Resolve.js @@ -25,11 +25,7 @@ module.exports = class extends ChainedMap { } plugin(name) { - if (!this.plugins.has(name)) { - this.plugins.set(name, new Plugin(this, name)); - } - - return this.plugins.get(name); + return this.plugins.getOrCompute(name, () => new Plugin(this, name)); } toConfig() { diff --git a/src/Rule.js b/src/Rule.js index f845961..45e1695 100644 --- a/src/Rule.js +++ b/src/Rule.js @@ -31,19 +31,11 @@ module.exports = class Rule extends ChainedMap { } use(name) { - if (!this.uses.has(name)) { - this.uses.set(name, new Use(this, name)); - } - - return this.uses.get(name); + return this.uses.getOrCompute(name, () => new Use(this, name)); } oneOf(name) { - if (!this.oneOfs.has(name)) { - this.oneOfs.set(name, new Rule(this, name)); - } - - return this.oneOfs.get(name); + return this.oneOfs.getOrCompute(name, () => new Rule(this, name)); } pre() { diff --git a/test/ChainedMap.js b/test/ChainedMap.js index 2ca69ae..07558a8 100644 --- a/test/ChainedMap.js +++ b/test/ChainedMap.js @@ -28,6 +28,14 @@ test('get', t => { t.is(map.get('a'), 'alpha'); }); +test('getOrCompute', t => { + const map = new ChainedMap(); + + t.is(map.get('a'), undefined); + t.is(map.getOrCompute('a', () => 'alpha'), 'alpha'); + t.is(map.get('a'), 'alpha'); +}); + test('clear', t => { const map = new ChainedMap();