4

我正在尝试从 java do F# 中移植一些代码,以在给定点周围生成多维点网格。我想出了这个:

let gridGenerator midpoint stepSize steps = 
    seq {
        let n = Array.length midpoint
        let direction = Array.create n -steps
        let mutable lastIndex = n-1
        while lastIndex>=0 do
            let next = midpoint |> Array.mapi (fun i x -> x+ direction.[i]*stepSize)
            while lastIndex>=0 && direction.[lastIndex]=steps do 
                direction.[lastIndex]<- (-steps)
                lastIndex<-lastIndex-1;        
            if lastIndex>=0 then
                direction.[lastIndex]<-direction.[lastIndex]+1;
                lastIndex <- n-1;
            yield next;
    }

除了这段代码非常必要(我会很感激如何修复它的提示),我得到一个编译错误:

Program.fs(18,15):错误 FS0407:可变变量“lastIndex”的使用方式无效。可变变量不能被闭包捕获。考虑通过“ref”和“!”消除这种突变的使用或使用堆分配的可变参考单元。

我该如何解决这个错误?我怎样才能使它更实用?

示例:对于 midpoint [|0.0, 1.0|],步长0.51我期望的步数(实际上是任何顺序)

seq{[|-0.5, 0.5|], [|-0.5, 1.0|], [|-0.5, 1.5|], [|0.0, 0.5|], [|0.0, 1.0|], [|0.0, 1.5|], [|0.5, 0.5|], [|0.5, 1.0|], [|0.5, 1.5|]}

另请注意,这将执行多次,因此性能至关重要。

4

3 回答 3

4
let gridGenerator midpoint stepSize steps =
    seq {
        let n = Array.length midpoint
        let direction = Array.create n -steps
        let lastIndex = ref (n - 1)
        while !lastIndex >= 0 do
            let next = midpoint |> Array.mapi (fun i x -> x + direction.[i] * stepSize)
            while !lastIndex >= 0 && direction.[!lastIndex] = steps do
                direction.[!lastIndex] <- -steps
                decr lastIndex
            if !lastIndex >= 0 then
                direction.[!lastIndex] <- direction.[!lastIndex] + 1
                lastIndex := n - 1
            yield next
    }

?

ref's 非常适合此类用途,并且不被视为可变变量(因为它们不是)。

于 2012-06-08T10:49:59.383 回答
4

这是一种更实用的方法:

let rec gridGenerator midpoint stepSize steps =
    match midpoint with
    | [] -> Seq.singleton []
    | p::point ->
        seq {
            for d in - stepSize * steps .. stepSize .. stepSize * steps do
                for q in gridGenerator point stepSize steps do
                    yield (p + d) :: q
        }

和签名:

val gridGenerator : int list -> int -> int -> seq<int list>

如果您重用结果,请记住将其缓存或转换(为数组或列表)。

于 2012-06-08T12:00:27.027 回答
3

现在你可以只使用 F# 4,它没有这样的约束。

于 2016-04-27T05:05:56.027 回答