【问题标题】:F# : Writing a function that builds a list of tuples recursively and change a mutable variableF#:编写一个函数,以递归方式构建元组列表并更改可变变量
【发布时间】:2011-12-12 13:41:47
【问题描述】:

这个问题和这个previous thread有关。

我按照 Tomas 的建议使用了这段代码,一切正常:

let GetSameColorNeighs (grid:Option<Ball>[,], row, col, color:Color) =
  let rec loop (row, col) = seq {
    if not (row < 0 || col < 0 || row > MaxLineNumber - 1 
                    || col > BallsPerLine - 1) then
        let ball = grid.[row,col]
        match ball with 
        | Some(ball) -> 
          if (!ball.visited = false || not <| ball.color.Equals(color)) then
            // Not sure what you want here - yield items using 'yield'?
            // [row , col] 
          else
            ball.visited := true
            yield row, col                 // Add single item to results
            yield! loop(row + 1, col + 1)  // Add all generated to results
            yield! loop(row - 1, col - 1)  //        -- || --
        | None  -> () }
  loop(row, col) |> Seq.toList

上面的代码遍历“球”的数组 2d 并返回具有相同颜色的相邻球的索引列表。

现在我必须修改函数,使其还返回一个布尔值,指示列表中的至少一个球是否满足特定条件。我以这种方式更改了代码,但似乎无法在该代码中分配可变值:

let GetSameColorNeighs (grid:Option<Ball>[,], row, col, color:Color)  : List<int * int> * bool =
    let mutable b : bool = false
    let rec loop (row, col) = seq {
        if not (row < 0 || col < 0 || row > MaxLineNumber - 1 
                        || col > BallsPerLine - 1) then
            let ball = grid.[row,col]
            match ball with 
            | Some(ball) -> 
              if (ball.visited = true || not <| ball.color.Equals(color)) then
                ()
              else
                //HERE's THE PROBLEM
                if (ball_satisfy_a_certain_condition) then
                      b <- true
                ball.visited := true
                yield row, col                 // Add single item to results
                yield! loop(row + 1, col + 1)  // Add all generated to results
                yield! loop(row - 1, col - 1)  //        -- || --
            | None  -> () }
      loop(row, col) |> Seq.toList, b

好像闭包不能获取可变变量(不知道是什么意思)。

所以我有两个问题:

  1. 为什么上面对可变变量的赋值是错误的?
  2. 我应该如何重构我的代码来实现这个目标?

【问题讨论】:

  • 更改为“让 b = ref false”

标签: recursion f# closures mutable


【解决方案1】:

简而言之,您必须使用ref 变量而不是可变变量。

虽然可变变量是在堆栈上分配的,但ref 变量是基于堆的。每次调用 loop 函数后,当 ref 值仍然存在时,可变值将被清除。因此,只有ref 值在GetSameColorNeighs 中返回是有效的。

这个问题已经在这里被问过很多次了。请参阅The mutable variable 'i' is used in an invalid way.?this blog post 进行更深入的讨论。

【讨论】:

  • +1 感谢您的链接。我会仔细阅读。顺便说一句,问题是我正在使用重新定义 := 运算符的第三方 f# 模块。因此,当我尝试执行 'b := false ' 时,会出现错误。您知道如何重新定义 ':=' 运算符以便在本地正常使用它吗?
  • 最简单的方法是使用b.contents &lt;- false 而不是b:=false。您可以按照en.wikibooks.org/wiki/F_Sharp_Programming/… 中的说明重新定义:=,但它会在任何地方覆盖当前的:= 运算符,这可能是您不想要的。
猜你喜欢
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 1970-01-01
  • 2017-10-28
  • 1970-01-01
  • 2016-12-11
相关资源
最近更新 更多