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
これは、ループが少なくとも1回実行されることを保証するため、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に達すると壊れますが、構文がまったく異なり、別の変数が導入されるなどです。)
これを試して:
exception BreakException
try
for i = 0 to 99 do
if i = 66 then
raise BreakException
with BreakException -> ()
一部の人々は例外を使用することを好まないことを私は知っています。しかし、それにはメリットがあります。
複雑な再帰関数について考える必要はありません。当然のことながらそれは可能ですが、場合によっては不必要に面倒であり、例外を使用する方が簡単です。
この方法では、ループ本体の途中でブレークできます。 (ブレーク「フラグ」メソッドも単純ですが、ループ本体の最後でのみブレークできます。)
ネストされたループから簡単に脱出できます。
最近、私は同様の状況を解決しようとしました:
たとえば、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 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
リストが含まれます。
seq {
for i = 0 to 99 do
if i = 66 then yield ()
}
|> Seq.tryItem 0
|> ignore
この種の問題には、再帰関数を使用できます。
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