summaryrefslogtreecommitdiff
path: root/js/util/memoize.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/util/memoize.js')
-rw-r--r--js/util/memoize.js45
1 files changed, 45 insertions, 0 deletions
diff --git a/js/util/memoize.js b/js/util/memoize.js
new file mode 100644
index 0000000..796c060
--- /dev/null
+++ b/js/util/memoize.js
@@ -0,0 +1,45 @@
+/*
+ * Helper function for memoization
+ *
+ * The passed labeller function must generate unique and exact names for entries that are naturally equal.
+ * IDs are persistent.
+ *
+ * names, idByName, and entries are accessible fields from the memoizer.
+ * Behaviour on external modification of these fields is undefined.
+ *
+ * An entry object passed to the memoizer has its field "id" set to the memoized id by default.
+ * The name of the ID field can be modified by calling the getter/setter idField() from the memoizer.
+ * Behaviour on changing the ID field used while the memoizer has already performed memoization is undefined.
+ */
+function memoize(labeller) {
+ var idField = "id";
+ var names = [];
+ var idByName = {};
+ var entries = [];
+ var _memoizer = function(entry) {
+ var name = labeller(entry);
+ if (name in idByName) {
+ /* We already have a suitable entry. */
+ var id = idByName[name];
+ return entries[id];
+ }
+ /* New entry. */
+ /* Set the entry's ID. */
+ entry[idField] = entries.length;
+ /* Index the new entry. */
+ idByName[name] = entry[idField];
+ names[entry[idField]] = name;
+ entries.push(entry);
+
+ return entry;
+ }
+ _memoizer.names = function() { return names; };
+ _memoizer.idByName = function() { return idByName; };
+ _memoizer.entries = function() { return entries; };
+ _memoizer.idField = function(x) {
+ if (!arguments.length) return idField;
+ idField = x;
+ return _memoizer;
+ };
+ return _memoizer;
+}