Я думаю, что вы всегда можете преобразовать цикл for для последовательности с одним эффектом (изменяющим локальную переменную) в код, который избавляет от изменяемого; Вот пример общего преобразования:
let inputSeq = [1;2;3]
// original mutable
let mutable x = ""
for n in inputSeq do
let nStr = n.ToString()
x <- x + nStr
printfn "result: '%s'" x
// immutable
let result =
inputSeq |> Seq.fold (fun x n ->
// the 'loop' body, which returns
// a new value rather than updating a mutable
let nStr = n.ToString()
x + nStr
) "" // the initial value
printfn "result: '%s'" result
В вашем конкретном примере есть вложенные циклы, поэтому вот пример, демонстрирующий одинаковое механическое преобразование в два этапа:
let inputSeq1 = [1;2;3]
let inputSeq2 = ["A";"B"]
let Original() =
let mutable x = ""
for n in inputSeq1 do
for s in inputSeq2 do
let nStr = n.ToString()
x <- x + nStr + s
printfn "result: '%s'" x
let FirstTransformInnerLoopToFold() =
let mutable x = ""
for n in inputSeq1 do
x <- inputSeq2 |> Seq.fold (fun x2 s ->
let nStr = n.ToString()
x2 + nStr + s
) x
printfn "result: '%s'" x
let NextTransformOuterLoopToFold() =
let result =
inputSeq1 |> Seq.fold (fun x3 n ->
inputSeq2 |> Seq.fold (fun x2 s ->
let nStr = n.ToString()
x2 + nStr + s
) x3
) ""
printfn "result: '%s'" result
(В приведенном выше коде я использовал имена «x2» и «x3», чтобы сделать область видимости более заметной, но вы можете просто использовать имя «x» во всем.)
Возможно, стоит попытаться сделать то же самое преобразование в вашем примере кода и опубликовать свой собственный ответ. Это не обязательно даст самый идиоматический код, но может быть упражнением в преобразовании цикла for в вызов Seq.fold.
(Тем не менее, в этом примере вся цель - в основном академическое упражнение - код с изменяемым 'отлично'.)