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

标签 scala functional-programming immutability monads

我正在尝试学习函数式编程禅宗,因此我正在使用纯函数式编程编写一个简单的编译器:Scala,任何地方都没有“var”,也没有可变结构。

我有一个“已评估函数”的缓存,以加快编译速度并避免在某些情况下无限递归。在命令式方法中,这将是对某处大型可变 HashMap 的引用。但在功能方法中,它更像下面的代码(经过大量简化和解释,请原谅任何语法错误)。

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)
}

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

   (cache1, newExpression)

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

这是一个常见错误吗?如何避免这种情况?

我会使用 do-syntax,但我觉得这只是一个更复杂的“var”。我一定是想错了......

最佳答案

这种情况并不常见,因为每个人都在使用State( scalazcats )。 如果您使用 State-monad(例如,来自上述库之一),您的示例应如下所示:

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

或者更确切地说

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

这假设compileExpression也有签名

def compileExpression(u: UncompiledExpr): State[Cache, CompiledExpr]

并且包含提供 for-yield 语法的所有具有隐式转换的导入。

关于scala - 如何避免使用错误数据版本的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51504282/

相关文章:

algorithm - 为Akka Actor 池排序了共享邮箱或总线?

scala - Play Framework : Logging time

haskell - 在 Haskell 中计算树中的元素

clojure - 使用 Clojure 帮助建立替换模型 [Sicp]

scala - 使用 Guice 绑定(bind)/注入(inject) Scala 函数(不是整个类)?

scala - 用 `type` 参数声明一个函数 `implicit`

python - 列表理解与 lambda + 过滤器

c# - 如何释放或回收 C# 中的字符串?

design-patterns - 在D中实现值对象模式

collections - 如何在迭代集合的同时修改集合?