我试图围绕纯粹的功能,但我不确定我是否真的理解它。我知道纯函数不应该改变外部状态,并且每次都应该返回相同的输出,只要它具有相同的输入。
我知道例如这个函数是不纯的,因为它改变了程序其他部分可能使用的cart变量:
const addToCart = (cart, item) => {
cart.push(item);
return cart;
};
纯态的相同功能:
const addToCart = (cart, item) => {
const newCart = lodash.cloneDeep(cart);
newCart.push(item);
return newCart;
};
这对我有意义。我已经知道纯函数应该总是返回一些东西。
但是,我正在研究一些需要我使用HTML5 canvas元素的东西,而且我有这个函数可以清除画布:
function clearCanvas(canvas) {
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
}
如何使上述功能纯净?我意识到它不纯,因为它不会返回任何东西,也会改变画布变量的状态。 DOM操作本质上是不纯的吗?
任何帮助将不胜感激:)
答案 0 :(得分:2)
DOM操纵是不纯的。你无法以“纯粹”的方式清除画布。
任何改变系统状态或与外界交互的东西据说都有side effects,在纯功能编程环境中,应避免副作用。
但是,DOM操作显然可以做到这两点;清除画布既是状态的改变(未清除也是清除),用户可以看到这种改变。
您可能希望深入了解functional programming,这似乎是您尝试使用纯/不纯函数方法实现的目标。
函数式编程的目的是避免改变状态,例如,一个程序在另一个程序使用它时不会更改对象,这可能会产生意外和不需要的结果。
答案 1 :(得分:2)
IO monad
你可能对IO monad感兴趣 - 本质上IO包含 thunk 或懒惰函数,它只在我们调用runIO
时运行。更重要的是,我们可以将事物置于IO中,map
是一个普通的函数,允许我们对所包含的值进行操作。
有关良好的阅读和其他IO实施,请参阅Brian Lonsdorf的书中的Chapter 9: Monadic Onions
小演示
// IO :: (void -> a) -> IO a
const IO = f => ({
// runIO :: void -> a
runIO: f,
// map :: IO a => (a -> b) -> IO b
map: g =>
IO(() => g(f())),
// chain :: IO a => (a -> IO b) -> IO b
chain: g =>
IO(g(f()).runIO)
})
// IO.of :: a -> IO a
IO.of = x => IO(() => x)
// log :: String -> a -> IO a
const log = label => x =>
IO(() => (console.log(label, x), x))
// $ :: String -> IO HTMLElement
const $ = x =>
IO(() => document.querySelector(x))
// getText :: HTMLElement -> String
const getText = e =>
e.textContent
// main :: String -> IO String
const main = selector =>
$(selector)
.map(getText)
.chain(log('A'))
.map(s => s.toUpperCase())
.chain(log('B'))
.runIO()
main('title')
// A hello world
// B HELLO WORLD
<title>hello world</title>
答案 2 :(得分:0)
通过函数编程范例
来实现function clearCanvas(canvas) {
const imgData = canvas.getContext('2d').getImageData(0,0,canvas.width,canvas.height);
new Uint32Array(imgData.data.buffer).set(0);
return data;
}
canvas.getContext('2d').setImageData(clearCanvas(canvas),0,0);
没有副作用,并为相同的参数返回相同的数据。
但功能性编程是一种防御性的风格,它假设代码是危险的并且危险必须被隔离。因此,它非常耗费资源并且速度慢,并且根本不适合高性能代码。