我正在尝试移植一些代码形式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'和'!'来消除这种突变的使用或使用堆分配的可变参考单元。
如何修复此错误?我怎样才能使它更具功能性?
示例:对于中点[|0.0, 1.0|]
,步长0.5
和步骤1
我期望(实际上是任何顺序)
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|]}
请注意,这将被执行多次,因此性能至关重要。
答案 0 :(得分: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
对于此类用途非常有用,并且不被视为可变变量(因为它们不是)。
答案 1 :(得分: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>
如果重复使用结果,请记住将其缓存或转换(转换为数组或列表)。
答案 2 :(得分:2)
现在你可以使用F#4,它没有这样的约束。