F#从while循环中断

F#从while循环中断,f#,while-loop,break,F#,While Loop,Break,有什么方法可以像C/C#那样做呢 例如(C#风格) for(int i=0;i

有什么方法可以像
C/C#
那样做呢

例如(C#风格)

for(int i=0;i<100;i++)
{
如果(i==66)
打破
} 

简短的回答是否定的。您通常会使用一些高阶函数来表示相同的功能。有很多函数可以让你做到这一点,对应于不同的模式(因此,如果你描述了你到底需要什么,有人可能会给你一个更好的答案)

例如,
tryFind
函数返回给定谓词返回的序列中的第一个值
true
,这样您就可以编写如下内容:

seq { 0 .. 100 } |> Seq.tryFind (fun i ->
  printfn "%d" i
  i=66)
实际上,如果您要表达一些高级逻辑,并且有相应的函数,那么这是最好的方法。如果您确实需要表示类似于
break
,则可以使用递归函数:

let rec loop n = 
  if n < 66 then 
    printfn "%d" n
    loop (n + 1)

loop 0      
让rec循环n=
如果n<66,则
printfn“%d”n
循环(n+1)
循环0

一个更奇特的选择(虽然效率不高,但对DSL来说可能更好)是,您可以定义一个计算表达式,让您编写
break
continue
,但正如我所说,这并没有那么有效。

您必须将其更改为while循环

let (i, ans) = (ref 0, ref -1)
while(!i < 100 and !ans < 0) do
 if !i = 66 then
   ans := !i
ans
let(i,ans)=(参考0,参考-1)
而(!i<100和!ans<0)则
如果!那么i=66
答:=!我
ans

(当我达到66时,这会中断——是的,语法非常不同,引入了另一个变量,等等)

这真的很难看,但在我的例子中它起了作用

let mutable Break = false
while not Break do
    //doStuff

    if breakCondition then
        Break <- true
done
let mutable Break=false
不破不破
//多斯塔夫
如果情况不好,那么

Break对于这类问题,可以使用递归函数

let rec IfEqualsNumber start finish num =
    if start = finish then false
    elif 
      start = num then true
    else
      let start2 = start + 1
      IfEqualsNumber start2 finish num
试试这个:

exception BreakException

try
    for i = 0 to 99 do
      if i = 66 then
        raise BreakException
with BreakException -> ()
我知道有些人不喜欢使用异常。但它也有优点

  • 您不必考虑复杂的递归函数。属于 因为你可以这样做,但有时这是不必要的麻烦 使用异常更简单

  • 此方法允许您在环体的一半处打断。(Break“flag”方法也很简单,但它只允许在循环体的末尾断开。)

  • 您可以轻松地从嵌套循环中退出


最近,我试图解决一个类似的问题:

例如,10条数据的列表。必须针对Restful服务器查询它们中的每一个,然后获取每个的结果

let lst = [4;6;1;8]
问题是:

  • 如果API调用失败(例如网络问题),则没有必要进行进一步调用,因为我们需要所有10个可用结果。当API调用失败时,整个过程应该尽快停止
天真的方法:使用
List.map()
惯用方法:使用递归 不太习惯,因为它使用异常来停止操作

exception MyException of string
let makeCall lstLocal =
    match lstLocal with
    | [] -> []
    | head::tail ->
        try
            use sqlComd = ...
            sqlComd.Parameters.Add("@Id", SqlDbType.BigInt).Value <- x
            let temp = sqlComd.ExecuteScala()
            temp :: makeCall (tail)
        with
            |:? System.Data.SqlClient.SqlException as ex -> raise MyException ex.Message

try
    let res = makeCall lst
    printfn "Here is the 10 results..."
with
    | :? MyException -> printfn "Something went wrong"
字符串异常MyException
让我们调用lstLocal=
匹配
| [] -> []
|头:尾->
尝试
使用sqlComd=。。。
参数。添加(“@Id”,SqlDbType.BigInt)。值提升MyException ex.消息
尝试
让res=makecalllst
printfn“这是10个结果…”
具有
| :? MyException->printfn“出了问题”
老式的命令式方法:
而。。。执行

这仍然需要
可变
列表。

而且因为它不会增加
i
,所以需要很长时间。:-)这是什么
:=
运算符?我的理解是,通过使用
rec
将F#函数声明为递归函数,它将有效地使用尾部递归来避免递归调用的堆栈分配,从而避免堆栈溢出错误。
val myList: List<string>
let res = lst |> List.tryFindIndex (fun x ->
    try
        use sqlComd = ...
        sqlComd.Parameters.Add("@Id", SqlDbType.BigInt).Value <- x
        myList.Add(sqlComd.ExecuteScala())
        false
    with
        |:? System.Data.SqlClient.SqlException as ex -> true
)

match res with
| Some _ -> printfn "Something went wrong"
| None -> printfn "Here is the 10 results..."
lst |> List.map (fun x -> 
    try
        use sqlComd = ...
        sqlComd.Parameters.Add("@Id", SqlDbType.BigInt).Value <- x
        sqlComd.ExecuteScala() |> Some
    with
        | :? System.Data.SqlClient.SqlException as ex -> None
)
val myList: List<string>
let res = lst |> List.tryFindIndex (fun x ->
    try
        use sqlComd = ...
        sqlComd.Parameters.Add("@Id", SqlDbType.BigInt).Value <- x
        myList.Add(sqlComd.ExecuteScala())
        false
    with
        |:? System.Data.SqlClient.SqlException as ex -> true
)

match res with
| Some _ -> printfn "Something went wrong"
| None -> printfn "Here is the 10 results..."
exception MyException of string
let makeCall lstLocal =
    match lstLocal with
    | [] -> []
    | head::tail ->
        try
            use sqlComd = ...
            sqlComd.Parameters.Add("@Id", SqlDbType.BigInt).Value <- x
            let temp = sqlComd.ExecuteScala()
            temp :: makeCall (tail)
        with
            |:? System.Data.SqlClient.SqlException as ex -> raise MyException ex.Message

try
    let res = makeCall lst
    printfn "Here is the 10 results..."
with
    | :? MyException -> printfn "Something went wrong"