代码之家  ›  专栏  ›  技术社区  ›  Verdagon

如何避免在使用错误版本的数据时出现错误?

  •  3
  • Verdagon  · 技术社区  · 7 年前

    我正在尝试学习函数式编程zen,所以我正在使用纯函数式编程编写一个简单的ish编译器: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)
    }
    

    但是,如果我有一个bug,最后一行是:

       (cache1, newExpression)
    

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

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

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

    1 回复  |  直到 7 年前
        1
  •  5
  •   Andrey Tyukin    7 年前

    这是不常见的,因为每个人都在使用 State ( scalaz , cats ). 如果你使用 国家 -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 包括语法。