我有这样一个功能:
let ScanColors() =
for i in 1..54 do
let mutable c = Unchecked.defaultof<string>
if (i = 9) then
c <- "U - WHITE"
else
if (i <> 0 && i%9 = 0) then
MoveSensor(SensorPos.THIRD)
else
MoveSensor(
match ((i - (i/9)*9)%2 <> 0) with
| true -> SensorPos.SECOND
| false -> SensorPos.FIRST)
while (true) do
c <- ScanColor()
if (c = "ERR") then
CalibrateSensorPosition()
else
break
ResetSensorPosition()
在这个函数中,在while
语句中,我不能使用break,因为如你所知,break
在F#中没有使用。我正在寻找break
的替代品,我看到了这个链接:
但说实话,我无法确定这个解决方案是否适合我的问题。
答案 0 :(得分:8)
可悲的是,F#不支持break
。有很多相当复杂的方法可以解决这个问题(例如this recent one或我的computation builder),但这些方法有缺点,会使代码相当复杂。
处理这个问题的一般方法是使用递归重写代码 - 这通常会编译为使用break
和continue
在C#中编写的IL。
因此,代码段中的while
块可以写成一个递归调用自身的函数,直到结果不是“ERR”,然后返回c
:
let rec scanWhileErr () =
let c = ScanColor()
if c = "ERR" then
CalibrateSensorPosition()
scanWhileErr()
else c
然后从主块调用此函数:
if (i <> 0 && i%9 = 0) then
MoveSensor(SensorPos.THIRD)
else
MoveSensor(if (i - (i/9)*9)%2 <> 0 then SensorPos.SECOND else SensorPos.FIRST)
c <- scanWhileErr ()
ResetSensorPosition()
除此之外,我还将你的match
布尔变为普通if
- 当你只有两个案例并且他们是布尔人时,使用match
而不是{ {1}}。
此外,我保留了您的可变变量if
,但我怀疑由于递归而不再需要它。
答案 1 :(得分:6)
中断,我个人会尝试避免在C#中断,因为有许多替代/更简洁的方法来打破循环。
保持命令式代码风格的简单修复将是:
c <- ScanColor()
while (c = "ERR") do
CalibrateSensorPosition()
c <- ScanColor()
ResetSensorPosition()
但是在F#中,可以进一步压缩这个单行:
while (c <- ScanColor(); c = "ERR") do CalibrateSensorPosition()
答案 2 :(得分:2)
实际上,我认为这种方法很好,并且适用于我的情况:
let mutable flag = true
while (flag = true) do
c <- ScanColor()
if (c = "ERR") then
CalibrateSensorPosition()
else
flag <- false
ResetSensorPosition()
答案 3 :(得分:0)
我认为一个简单的方法就是当你需要在循环中有一个“中断”然后你确保循环终止时。
这样做的一个例子就是如果我们有一个看起来像这样的while循环
while i < upperlimit do
if a
then break