【发布时间】:2021-12-16 09:42:08
【问题描述】:
我有这样的代码:
A = [1,2,3]
if (condition) {A.push(4)}
A.push(5)
但我的数组实际上是不可变的,所以我不能这样做。我怎样才能在一个表达式中完成所有操作?我不希望中间有一个空值。
【问题讨论】:
标签: javascript functional-programming immutability
我有这样的代码:
A = [1,2,3]
if (condition) {A.push(4)}
A.push(5)
但我的数组实际上是不可变的,所以我不能这样做。我怎样才能在一个表达式中完成所有操作?我不希望中间有一个空值。
【问题讨论】:
标签: javascript functional-programming immutability
这是一种方法:
A = [1, 2, 3, ...(condition ? [4] : []), 5]
如果这在您的代码库中很常见,并且您希望保持未定义,那么您可以编写一个带有哨兵的过滤器函数。
const REMOVE = symbol('removeme')
const A = clean([1, 2, 3, condition ? 4 : REMOVE, 5])
function clean(arr) {return arr.filter(x=>x!==REMOVE)}
【讨论】:
你可以在这里使用Writer monad。
// type Writer t a = { value :: a, array :: [t] }
// pure :: a -> Writer t a
const pure = (value) => ({ value, array: [] });
// bind :: (Writer t a, a -> Writer t b) -> Writer t b
const bind = (writerA, arrow) => {
const writerB = arrow(writerA.value);
const array = [...writerA.array, ...writerB.array];
return { value: writerB.value, array };
};
// tell :: [t] -> Writer t ()
const tell = (array) => ({ value: undefined, array });
const writer = (gen) => {
const next = (data) => {
const { value, done } = gen.next(data);
return done ? value : bind(value, next);
};
return next(undefined);
};
const example = (condition) => writer(function* () {
yield tell([1, 2, 3]);
if (condition) yield tell([4]);
return tell([5]);
}());
console.log(example(true).array); // [1,2,3,4,5]
console.log(example(false).array); // [1,2,3,5]
【讨论】:
Reap 和Sow 模式,所以我也为gist.github.com/qpwo/1a79842bd5ac416e4761a579182174fe 做了一个要点。喜欢 haskell 类型的 cmets——让我以不同的方式看待 JS。