用功能代码替换while循环

时间:2016-11-03 17:17:08

标签: scala functional-programming

我正在重构一些scala代码,我遇到了一个while循环问题。旧代码是:

for (s <- sentences){
// ...
   while (/*Some condition*/){
      // ...
      function(trees, ...)
   }
}

我已将该代码翻译成此代码,使用foldLeft横向sentences

sentences./:(initialSeed){
 (seed, s) =>
     // ...
     // Here I've replaced the while with other foldleft 
     trees./:(seed){
         (v, n) =>
             // ....
             val updatedVariable = function(...., v)
     }
}

现在,我可能需要在完全横向之前停止横穿trees(内部foldLeft),因为我发现了这个问题:

Abort early in a fold

但我也有以下问题:

当我横向trees时,我需要将值累加到变量vfunction需要v并返回更新的v,此处称为updatedVariable {1}}。问题是我觉得这不是编码这种功能的正确方法。

你能否推荐我一种功能/不可改变的方法呢?

注意:我已经简化了代码以显示实际问题,完整的代码是:

val trainVocabulart = sentences./:(Vocabulary()){
  (vocab, s) =>
    var trees = s.tree
    var i = 0
    var noConstruction = false

    trees./:(vocab){
      (v, n) =>
        if (i == trees.size - 1) {
          if (noConstruction) return v
          noConstruction = true
          i = 0
        } else {
          // Build vocabulary
          val updatedVocab = buildVocabulary(trees, v, i, Config.LeftCtx, Config.RightCtx)

          val y = estimateTrainAction(trees, i)

          val (newI, newTrees) = takeAction(trees, i, y)

          i = newI
          trees = newTrees

          // Execute the action and modify the trees
          if (y != Shift)
            noConstruction = false

          Vocabulary(v.positionVocab ++ updatedVocab.positionVocab,
            v.positionTag ++ updatedVocab.positionTag,
            v.chLVocab ++ updatedVocab.chLVocab,
            v.chLTag ++ updatedVocab.chLTag,
            v.chRVocab ++ updatedVocab.chRVocab,
            v.chRTag ++ updatedVocab.chRTag)
        }
      v
    }
}

旧的:

for (s <- sentences) {
  var trees = s.tree
  var i = 0
  var noConstruction = false
  var exit = false
  while (trees.nonEmpty && !exit) {
    if (i == trees.size - 1) {
      if (noConstruction) exit = true
      noConstruction = true
      i = 0
    } else {
      // Build vocabulary
      buildVocabulary(trees, i, LeftCtx, RightCtx)

      val y = estimateTrainAction(trees, i)

      val (newI, newTrees) = takeAction(trees, i, y)

      i = newI
      trees = newTrees

      // Execute the action and modify the trees
      if (y != Shift)
        noConstruction = false
    }
  }
}

1 个答案:

答案 0 :(得分:1)

第1页 - 你不能轻易做到这一点。您的简化或完整示例都不够完整,无法编译。

第二 - 你可以找到一些解决早期突破问题的合理解决方案的链接。有没有理由为什么它们看起来都不适合你的情况呢?

3 - 这个完整的例子真的有效吗?你正在折叠var ...

trees./:(vocab){

...并在该操作中修改/更新var ...

trees = newTrees

根据我的测试,这是一个毫无意义的陈述。通过更新集合,原始迭代不会改变。

第四 - 我不相信fold就是你想要的。 fold遍历集合并将其缩减为单个值,但您的目标似乎并不是找到单个值。您/:的结果将被丢弃。没有val result = trees./:(vocab){...

您可能会看到的一个解决方案是:trees.forall{ ...在每次迭代结束时,如果下一次迭代应该继续,则只返回true