2013-05-14 4 views

ответ

23

Короткий ответ: нет. Обычно вы используете функцию более высокого порядка, чтобы выразить ту же функциональность. Существует ряд функций, которые позволяют вам делать это, соответствующие различным шаблонам (поэтому, если вы описываете, что именно вам нужно, кто-то может дать вам лучший ответ).

Например, 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. Here is an example, но, как я уже сказал, это не так эффективно.

4

Вы должны изменить его на цикл while.

let (i, ans) = (ref 0, ref -1) 
while(!i < 100 and !ans < 0) do 
if !i = 66 then 
    ans := !i 
ans 

(Это нарушает, когда я добираюсь до 66 - но да синтаксис совсем другой, другой переменным вводятся, и т.д.)

+1

И поскольку он не увеличивает 'i', это занимает очень много времени. :-) –

2

Это действительно некрасиво, но в моем случае это сработало.

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

    if breakCondition then 
     Break <- true 
done 

Это полезно для циклов do-while, поскольку оно гарантирует, что цикл выполняется хотя бы один раз.

Надеюсь, что есть более элегантное решение. Мне не нравится рекурсивный, потому что я боюсь переполнения стека. :-(

0
seq { 
    for i = 0 to 99 do 
     if i = 66 then yield() 
} 
|> Seq.tryItem 0 
|> ignore 
0

Для такого рода проблем, которые вы могли бы использовать рекурсивную функцию

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 
0

Попробуйте это:.

exception BreakException 

try 
    for i = 0 to 99 do 
     if i = 66 then 
     raise BreakException 
with BreakException ->() 

Я знаю, что некоторые люди не любят использовать за исключением случаев, но оно имеет основания.

  • Вы не нужно думать о сложной рекурсивной функции. Из вы можете это сделать, но иногда это излишне надоедливо и использование исключения проще.

  • Этот метод позволяет разрывать половину тела петли. (Метод «Флаг» тоже прост, но он только позволяет разбить в конце тела цикла.)

  • Вы можете легко выйти из вложенного цикла.