Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/428.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 不变的记忆——可能吗?_Javascript_Immutability - Fatal编程技术网

Javascript 不变的记忆——可能吗?

Javascript 不变的记忆——可能吗?,javascript,immutability,Javascript,Immutability,我正试图保持我的前端堆栈在功能上尽可能的纯净和不变,它为这个项目创造了奇迹 据说所有可以可变实现的算法都可以不可变地实现,那么在javascript中,我应该如何实现不可变的函数记忆器呢?因为为了通过函数中的不同路径返回,函数内部或外部的一些状态必须改变 使用下面的函数,如何在javascript中实现不可变的记忆 function once(fn){ let returnValue; let canRun = true; return function runOnce(){

我正试图保持我的前端堆栈在功能上尽可能的纯净和不变,它为这个项目创造了奇迹

据说所有可以可变实现的算法都可以不可变地实现,那么在javascript中,我应该如何实现不可变的函数记忆器呢?因为为了通过函数中的不同路径返回,函数内部或外部的一些状态必须改变

使用下面的函数,如何在javascript中实现不可变的记忆

function once(fn){
  let returnValue;
  let canRun = true;
  return function runOnce(){
      if(canRun) {
          returnValue = fn.apply(this, arguments);
          canRun = false;
      }
      return returnValue;
  }
}
var processonce = once(process);
processonce(); //process
processonce(); //

我对这个问题也很好奇。我同意@zch-传递不可变状态将起作用(初始调用将使用空状态初始化递归)

所以,我做了关于实现斐波那契函数的家庭作业:记住,对于
n-1
n-2
我们至少需要它两次。当我们调用
fib(n-2)
-它已经被记忆

以下是我的实现:

const resultCombination = cache => result => (getResult = true) => getResult ? result : cache
const cacheResult = ({resultCombination}) => result => n => resultCombination({...result(false), [n]: result()})(result())

const memoize = ({resultCombination, cacheResult}) => cache => f => n => cache.hasOwnProperty(n)
    ? resultCombination(cache)(cache[n])
    : cacheResult({resultCombination})(f(cache)(n))(n)

const fib2 = ({resultCombination, cacheResult, memoize}) => f1Result => f => n => resultCombination(f1Result(false))(f1Result() + memoize({resultCombination, cacheResult})(f1Result(false))(f)(n - 2)())

const fib = ({resultCombination, cacheResult, memoize, fib2}) => cache => n => n === 1 || n === 2
    ? resultCombination(cache)(1)
    : fib2({resultCombination, cacheResult, memoize})(memoize({resultCombination, cacheResult})(cache)(fib({resultCombination, cacheResult, memoize, fib2}))(n - 1))(fib({resultCombination, cacheResult, memoize, fib2}))(n)


console.log('THE RESULT: ' + fib({
    resultCombination,
    cacheResult: ({resultCombination}) => result => n => {
        console.log(`Caching result: f(${n})=${result()}`)
        return cacheResult({resultCombination})(result)(n)
    },
    memoize: ({resultCombination, cacheResult}) => cache => f => n => {
        console.log(cache.hasOwnProperty(n) ? `Cache hit for n=${n}` : `Calculating value for f(${n})`)
        return memoize({resultCombination, cacheResult})(cache)(f)(n)
    },
    fib2
})({})(8)(true))

// Calculating value for f(7)
// Calculating value for f(6)
// Calculating value for f(5)
// Calculating value for f(4)
// Calculating value for f(3)
// Calculating value for f(2)
// Caching result: f(2)=1
// Calculating value for f(1)
// Caching result: f(1)=1
// Caching result: f(3)=2
// Cache hit for n=2
// Caching result: f(4)=3
// Cache hit for n=3
// Caching result: f(5)=5
// Cache hit for n=4
// Caching result: f(6)=8
// Cache hit for n=5
// Caching result: f(7)=13
// Cache hit for n=6
// THE RESULT: 21
为了更好地理解正在发生的事情,
cacheResult
memoize
函数被注入了日志包装器。如您所见,所有函数都是纯函数,只使用一个参数(依赖项注入除外)

请确保,
resultcomposition(cache)(result)
-只是取代了
{cache,result}
数据结构


另外,我不是Haskell的书呆子(甚至连Haskell或Lisp语法都不知道),但我对函数式编程很感兴趣

我提出了一种不同的io方法,使用生成器我们能说它是纯的吗

函数*\u cache(){
常量值=产量为空
而(真实)收益率
}
常量缓存=_缓存()
常量重计算=i=>{
log(`uh-oh这是一些繁重的计算`)
返回i++
}
cache.next()值
cache.next(重计算(1))
cache.next()值
cache.next()值
然后,您可以使用它在运行时缓存值

函数*\u cache(){
常量值=产量为空
而(真实)收益率
}
常量缓存=_缓存()
const loadMongo=uri=>void console.log(`full-loaded${uri}`)
功能结束(loadedMongo){
log('handler called')
}
函数处理程序(){
const mongoUri='Saloos speculos'
const loaded=cache.next().value
如果(已加载===null){
cache.next(loadMongo(mongoUri))
结束(cache.next().value)
}其他端(已加载)
}
handler()
handler()
handler()
handler()
handler()

记忆本质上依赖于状态,无法删除。充其量,您可以通过显式地传递状态使其“纯功能化”。状态将是不变的数据结构,但每次调用后都会有一个不同的数据结构。非常有趣,我将在下班回家后更深入地了解这一点。看起来很可靠,但是我试图避免传递表示“缓存”或“不缓存”的内容,并让函数固有地知道以前是否调用过它。显然,这在某种程度上需要可变性,但如果这种可变性可能存在于我的代码库之外的某个地方(例如javascript引擎本身),那么这是我可以接受的。例如,Redux确实存在状态突变,但根据Redux的思想,所有突变都是不可变的,您应该有一个全局存储。例如,我让我的库实现与Redux接口一致的备忘录(但不是强制性的Redux-您可以编写适配器以符合Redux接口和我的库)该库允许我灵活、模块化,并且仍然具有单一的全局状态。