Repository: calmm-js/partial.lenses
Pull request #34 (2016-12-07 03:29:41)

Added `skip` and `when`


Patch:
diff --git a/README.md b/README.md
index 9528c48..86dff82 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,8 @@ elements.
     * [Traversals and combinators](#traversals-and-combinators)
       * [`L.optional`](#optional "L.optional :: PTraversal a a")
       * [`L.sequence`](#sequence "L.sequence :: PTraversal [a] a")
+      * [`L.skip`](#skip "L.skip :: PTraversal a b")
+      * [`L.when`](#when "L.when :: (Maybe a -> Boolean) -> PTraversal a a")
   * [Debugging](#debugging)
     * [`L.log(...labels)`](#log "L.log :: (...Any) -> Lens s s")
 * [Background](#background)
@@ -1053,7 +1055,7 @@ L.modify(flatten, x => x+1, [[[1], 2], 3, [4, [[5]], [6]]])
 // [ [ [ 2 ], 3 ], 4, [ 5, [ [Object] ], [ 7 ] ] ]
 ```
 ```js
-L.modify(flatten, x => 3 <= x && x <= 5 ? undefined : x, [[[1], 2], 3, [4, [[5]], [6]]])
+L.remove([flatten, L.when(x => 3 <= x && x <= 5)], [[[1], 2], 3, [4, [[5]], [6]]])
 // [ [ [ 1 ], 2 ], [ [ 6 ] ] ]
 ```
 
@@ -1304,7 +1306,7 @@ L.modify(values, x => -x, sampleBST)
 //   smaller: { key: 'a', value: -2, greater: { key: 'b', value: -3 } } }
 ```
 ```js
-L.modify(values, x => x <= 2 ? undefined : x, sampleBST)
+L.remove([values, L.when(R.gte(2))], sampleBST)
 // { key: 'b', value: 3 }
 ```
 
@@ -1341,6 +1343,32 @@ L.modify(["xs", L.sequence, "x"], R.add(1), {xs: [{x: 1}, {x: 2}]})
 // { xs: [ { x: 2 }, { x: 3 } ] }
 ```
 
+##### <a name="skip"></a>[`L.skip`](#skip "L.skip :: PTraversal a b")
+
+`L.skip` is a traversal of no elements.
+
+For example:
+
+```js
+L.collect([L.sequence,
+           L.choose(x => (R.is(Array, x) ? L.sequence :
+                          R.is(Object, x) ? "x" :
+                          L.skip))],
+          [1, {x: 2}, [3,4]])
+// [ 2, 3, 4 ]
+```
+
+##### <a name="when"></a>[`L.when`](#when "L.when :: (Maybe a -> Boolean) -> PTraversal a a")
+
+`L.when` allows one to selectively skip elements within a traversal.
+
+For example:
+
+```js
+L.modify([L.sequence, L.when(x => x > 0)], R.negate, [0,-1,2,-3,4])
+// [ 0, -1, -2, -3, -4 ]
+```
+
 ### Debugging
 
 #### <a name="log"></a>[`L.log(...labels)`](#log "L.log :: (...Any) -> Lens s s")
diff --git a/src/partial.lenses.js b/src/partial.lenses.js
index 3c7f313..3156f7e 100644
--- a/src/partial.lenses.js
+++ b/src/partial.lenses.js
@@ -437,11 +437,15 @@ export const sequence = (A, x2yA, xs) =>
   ? emptyArrayToUndefined(mapPartialU(x2yA, mkArray(xs)))
   : A.map(emptyArrayToUndefined, PartialArray.traverse(A, x2yA, mkArray(xs)))
 
-export function optional(A, x2yA, x) {
+
+export const when = p => (A, x2yA, x) => {
   notGet(A)
-  return isDefined(x) ? x2yA(x) : A.of(undefined)
+  return p(x) ? x2yA(x) : A.of(x)
 }
 
+export const optional = when(isDefined)
+export const skip = when(always(false))
+
 export function branch(template) {
   const keys = []
   const vals = []


Test patch:
diff --git a/test/tests.js b/test/tests.js
index 0187a07..86446b8 100644
--- a/test/tests.js
+++ b/test/tests.js
@@ -84,6 +84,7 @@ describe("arities", () => {
   testEq('L.set.length', 3)
   testEq('L.to.length', 1)
   testEq('L.valueOr.length', 1)
+  testEq('L.when.length', 1)
 })
 
 describe('L.find', () => {
@@ -298,6 +299,16 @@ describe("L.optional", () => {
   testEq('L.modify([L.sequence, "x", L.optional, L.sequence], x => x < 2 ? undefined : x-1, [{x: [1, 2]}, {y: 2}, {x: [3], z: 1}])', [{x: [1]}, {y: 2}, {x: [2], z: 1}])
 })
 
+describe("L.skip", () => {
+  testEq('L.collect([L.sequence, L.skip], [1,3])', [])
+  testEq('L.remove([L.sequence, L.skip], [1,2])', [1,2])
+})
+
+describe("L.when", () => {
+  testEq('L.collect([L.sequence, L.when(x => x > 2)], [1,3,2,4])', [3,4])
+  testEq('L.modify([L.sequence, L.when(x => x > 2)], R.negate, [1,3,2,4])', [1,-3,2,-4])
+})
+
 describe("L.collect", () => {
   testEq('L.collect(["xs", L.sequence, "x", L.sequence], {xs: [{x:[3,1]},{x:[4,1]},{x:[5,9,2]}]})', [3,1,4,1,5,9,2])
   testEq('L.collect([L.sequence, "x", L.sequence], [{x: [1]}, {}, {x: []}, {x: [2, 3]}])', [1, 2, 3])