有什么办法可以做到C/C#
吗?
例如(C# 风格)
for (int i = 0; i < 100; i++)
{
if (i == 66)
break;
}
有什么办法可以做到C/C#
吗?
例如(C# 风格)
for (int i = 0; i < 100; i++)
{
if (i == 66)
break;
}
最简洁的答案是不。您通常会使用一些高阶函数来表达相同的功能。有许多功能可以让你做到这一点,对应于不同的模式(所以如果你描述了你到底需要什么,有人可能会给你一个更好的答案)。
例如,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
一个更奇特的选择(效率不高,但可能对 DSL 很好)是您可以定义一个计算表达式,让您编写break
和continue
. 这是一个例子,但正如我所说,这不是那么有效。
这真的很难看,但在我的情况下它有效。
let mutable Break = false
while not Break do
//doStuff
if breakCondition then
Break <- true
done
这对于 do-while 循环很有用,因为它保证循环至少执行一次。
我希望有一个更优雅的解决方案。我不喜欢递归的,因为我害怕堆栈溢出。:-(
您必须将其更改为 while 循环。
let (i, ans) = (ref 0, ref -1)
while(!i < 100 and !ans < 0) do
if !i = 66 then
ans := !i
ans
(当我达到 66 时,这会中断——但是是的,语法完全不同,引入了另一个变量,等等。)
seq {
for i = 0 to 99 do
if i = 66 then yield ()
}
|> Seq.tryItem 0
|> ignore
Try this:
exception BreakException
try
for i = 0 to 99 do
if i = 66 then
raise BreakException
with BreakException -> ()
I know that some folks don't like to use exceptions. But it has merits.
You don't have to think about complicated recursive function. Of cause you can do that, but sometimes it is unnecessarily bothersome and using exception is simpler.
This method allows you to break at halfway of the loop body. (Break "flag" method is simple too but it only allows to break at the end of the loop body.)
You can easily escape from nested loop.
最近我试图解决类似的情况:
例如,10 条数据的列表。它们中的每一个都必须针对一个 Restful 服务器进行查询,然后为每个得到一个结果。
let lst = [4;6;1;8]
问题:
List.map()
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
)
但如前所述,这不是最佳的。当发生失败的 API 时,会继续处理剩余的项目。无论如何,他们都会做一些最终被忽略的事情。
List.tryFindIndex()
与 不同map()
,我们必须将结果存储在 lamda 函数中的某个位置。一个合理的选择是使用mutable
列表。因此,当tryFindIndex()
返回时None
,我们知道一切正常,可以开始使用mutable
列表。
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 来停止操作。
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"
while... do
这仍然涉及mutable
列表。
对于这类问题,您可以使用递归函数。
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