| 1067 | return this.refine(Predicate.isNotUndefined, { expected: "a value other than `undefined`" }) |
| 1068 | } |
| 1069 | forEach<S, A, B>(this: Traversal<S, A>, f: (iso: Iso<A, A>) => Optional<A, B>): Traversal<S, B> { |
| 1070 | const inner = f(id<A>()) |
| 1071 | return makeOptional<S, ReadonlyArray<B>>( |
| 1072 | // GET: collect focused Bs |
| 1073 | (s) => |
| 1074 | Result.map(this.getResult(s), (as) => { |
| 1075 | const bs: Array<B> = [] |
| 1076 | for (let i = 0; i < as.length; i++) { |
| 1077 | const r = inner.getResult(as[i]) |
| 1078 | if (Result.isSuccess(r)) bs.push(r.success) |
| 1079 | } |
| 1080 | return bs |
| 1081 | }), |
| 1082 | // SET: bs must match the number of focusable elements |
| 1083 | (bs, s) => |
| 1084 | Result.flatMap(this.getResult(s), (as) => { |
| 1085 | // 1) collect focusable indices |
| 1086 | const idxs: Array<number> = [] |
| 1087 | for (let i = 0; i < as.length; i++) { |
| 1088 | if (Result.isSuccess(inner.getResult(as[i]))) idxs.push(i) |
| 1089 | } |
| 1090 | |
| 1091 | // 2) arity check |
| 1092 | if (bs.length !== idxs.length) { |
| 1093 | return Result.fail( |
| 1094 | new SchemaIssue.InvalidValue({ |
| 1095 | message: `each: replacement length mismatch: ${bs.length} !== ${idxs.length}` |
| 1096 | }) |
| 1097 | ) |
| 1098 | } |
| 1099 | |
| 1100 | // 3) update those indices |
| 1101 | const out: Array<A> = as.slice() |
| 1102 | for (let k = 0; k < idxs.length; k++) { |
| 1103 | const i = idxs[k] |
| 1104 | const r = inner.replaceResult(bs[k], as[i]) |
| 1105 | if (Result.isFailure(r)) { |
| 1106 | return Result.fail(new SchemaIssue.Pointer([i], r.failure)) |
| 1107 | } |
| 1108 | out[i] = r.success |
| 1109 | } |
| 1110 | return this.replaceResult(out, s) |
| 1111 | }) |
| 1112 | ) |
| 1113 | } |
| 1114 | modifyAll<S, A>(this: Traversal<S, A>, f: (a: A) => A): (s: S) => S { |
| 1115 | return (s) => |
| 1116 | Result.getOrElse( |