В выражениях цикла F # for
и while
отсутствуют возможности, общие для других языков:
continue
- пропустить остаток цикла и перезапустить его с начала выражения цикла.
break
- преждевременно остановить цикл.
Если вы хотите, чтобы continue
и break
не делали то, что я делал в начале, напишите очень сложное тестовое выражение для циклов while
. Вместо этого хвостовая рекурсия - лучший ответ в F #:
let vs : int [] = ...
let rec findPositiveNumberIndex i =
if i < vs.Length then
if vs.[i] > 0 then
Some i
else
findPositiveNumberIndex (i + 1)
else
None
match findPositiveNumberIndex 0 with
| Some i -> printfn "First positive number index: %d" i
| None -> printfn "No positive numbers found"
В коде, подобном этому, F # применяет нечто, называемое оптимизацией хвостового вызова (TCO), которое преобразует приведенный выше код в цикл while
с break
. Это означает, что мы не исчерпаем пространство стека, и цикл эффективен. TCO - это функция, которой нет в C #, поэтому мы не хотим писать код, подобный описанному выше, в C #.
Как и другие говорят с хвостовой рекурсией, иногда можно избежать изменчивого состояния, но это еще не все.
С помощью рекурсии хвоста ваши выражения цикла могут возвращать хороший результат.
Кроме того, если вы хотите быстро выполнять итерацию в F # для таких типов, как int64
или с приращением, отличным от 1
и -1
, вы должны полагаться на хвостовую рекурсию. Причина в том, что F # делает только эффективные for
выражения для целых и приращений 1
и -1
.
for i in 0..100 do
printfn "This is a fast loop"
for i in 0..2..100 do
printfn "This is a slow loop"
for i in 0L..100L do
printfn "This is a slow loop"
Иногда, когда вы охотитесь за производительностью, хитрость заключается в цикле к 0
(сохраняет регистр процессора). К сожалению, способ, которым F # генерирует код цикла for
, работает не так хорошо, как хотелось бы надеяться:
for i = 100 downto 0 do
printfn "Unfortunately this is not as efficient as it can be"
Хвостовая рекурсия в направлении 0
сохраняет регистр ЦП.
(К сожалению, компилятор F # не объединяет тест и инструкцию цикла для хвостовой рекурсии, так что это не так хорошо, как могло бы быть)