Browse Source

Extract chain and copyOnModification.

Herby Vojčík 5 years ago
parent
commit
c7c65f797a
1 changed files with 17 additions and 21 deletions
  1. 17 21
      src/cow-value-model.js

+ 17 - 21
src/cow-value-model.js

@@ -57,35 +57,31 @@ export const deepGetOrNil = (...keyDescriptions) => {
 
 export const deget = deepGetOrNil;
 
-export const deepCopyOnWrite = (...keyDescriptions) => {
-    const keys = constructKeys(keyDescriptions);
+const chain = (list, stop, step) => (function worker (index) {
+    return index >= list.length ? stop : step(list[index], worker(index + 1));
+})(0);
 
-    function setVal (x, index, val) {
-        if (index >= keys.length) return val;
-        const key = keys[index],
-            value = getKey(x, key),
-            modified = setVal(value, index + 1, val);
-        return value === modified ? x : copyWith(x, key, modified);
-    }
+const copyOnModification = (obj, key, value, modifierFn) => {
+    const modified = modifierFn(value);
+    return value === modified ? obj : copyWith(obj, key, modified);
+};
 
-    return val => obj => setVal(obj, 0, val);
+export const deepCopyOnWrite = (...keyDescriptions) => {
+    const keys = constructKeys(keyDescriptions);
+    return val => chain(keys, () => val, (key, next) => x =>
+        copyOnModification(x, key, getKey(x, key), next)
+    );
 };
 
 export const decow = deepCopyOnWrite;
 
 export const deepCopyOnMap = (...keyDescriptions) => {
     const keys = constructKeys(keyDescriptions);
-
-    function mapFn (x, index, fn) {
-        if (index >= keys.length) return fn(x);
-        const key = keys[index],
-            value = getKeyWithCheck(x, key);
-        if (value == null) return x;
-        const modified = mapFn(value.value, index + 1, fn);
-        return value.value === modified ? x : copyWith(x, key, modified);
-    }
-
-    return fn => obj => mapFn(obj, 0, fn);
+    return fn => chain(keys, fn, (key, next) => x => {
+        const valueWithCheck = getKeyWithCheck(x, key);
+        if (valueWithCheck == null) return x;
+        return copyOnModification(x, key, valueWithCheck.value, next);
+    });
 };
 
 export const decomap = deepCopyOnMap;