如何避免使用错误版本数据的错误?

Ver*_*gon 3 monads functional-programming scala immutability

我正在尝试学习函数式编程zen,所以我正在编写一个使用纯函数式编程的简单编译器:Scala,在任何地方都没有'var',也没有可变结构.

我有一个"已经评估过的函数"的缓存来加速编译并避免在某些情况下无限递归.在命令式方法中,这可能是某个地方的大型可变哈希映射的引用.但在功能方法中,它更像是下面的代码(大大简化和释义,原谅任何语法错误).

def compileAdd(
      cache0: Cache,
      uncompiledLeftSubExpr: UncompiledExpr,
      uncompiledRightSubExpr: UncompiledExpr)
: (Cache, CompiledExpr) = {
   val (cache1, compiledLeftSubExpr) =
         compileExpression(cache0, uncompiledLeftSubExpr)
   val (cache2, compiledRightSubExpr) =
         compileExpression(cache1, uncompiledRightSubExpr)
   val newExpression =
         AddExpression(compiledLeftSubExpr, compiledRightSubExpr)
   (cache2, newExpression)
}
Run Code Online (Sandbox Code Playgroud)

但是,想象一下,如果我有一个最后一行的错误:

   (cache1, newExpression)
Run Code Online (Sandbox Code Playgroud)

我做这一切的时候.这是我重构后错误的主要来源; 在移动代码后,我不可避免地忘记更新其中一个"版本号"并意外使用旧版本.

这是一个常见的错误吗?如何避免它?

我会使用do-syntax,但这让我觉得只是一个更复杂的"var".我一定在想这个错误......

And*_*kin 5

这种情况并不常见,因为每个人都在使用State(scalaz,).如果您使用State-monad(例如,来自其中一个提到的库),您的示例应该看起来像这样:

def compileAdd(
  uncompiledLeftSubExpr: UncompiledExpr,
  uncompiledRightSubExpr: UncompiledExpr
): State[Cache, CompiledExpr] = for {
   compiledLeftSubExpr <- compileExpression(uncompiledLeftSubExpr)
   compiledRightSubExpr <- compileExpression(uncompiledRightSubExpr)
} yield AddExpression(compiledLeftSubExpr, compiledRightSubExpr)
Run Code Online (Sandbox Code Playgroud)

更确切地说

def compileAdd(
  left: UncompiledExpr,
  right: UncompiledExpr
): State[Cache, CompiledExpr] = for {
   a <- compileExpression(left)
   b <- compileExpression(right)
} yield AddExpression(a, b)
Run Code Online (Sandbox Code Playgroud)

这假定compileExpression也有签名

def compileExpression(u: UncompiledExpr): State[Cache, CompiledExpr]
Run Code Online (Sandbox Code Playgroud)

并且for-yield包含了提供语法的所有带有implicits转换的导入.