将 F# while-do "mutable" 代码重构为功能性 "immutable" 代码
Refactoring F# while-do "mutable" code into functional "immutable" code
我一直在尝试将我的一个简单的 C# 控制台应用程序重新编写为纯函数式 F# 代码(如果可能的话)。到目前为止,我已经设法在 Seq 的帮助下将 while 块重写为“不可变”F#(类似于 Seq.initInfinite sequenceGenerator |> Seq.takeWhile 条件 |> Seq.iter bodyOfWhileCycle) - “F# for Fun and Profit”网站一直是我的灵感来源。
然而,这次我遇到了一个简单的 while 块,它在“可变”F# 中看起来如下(并且有效):
printfn "Type low OP number"
let mutable lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number"
let mutable highLimit = parseMe (Console.ReadLine())
let mutable myCondition = true
if highLimit > lowLimit then myCondition <- false
while myCondition do
printfn "Type low OP number again"
lowLimit <- parseMe (Console.ReadLine())
printfn "Type high OP number again"
highLimit <- parseMe (Console.ReadLine())
if highLimit > lowLimit then myCondition <- false
谁能帮我弄清楚如何将这个“可变”while-do 块重构为函数式样式? 我的尝试重构它不能按照我想要的方式工作——我不知道如何从 bodyOfWhileCycle 函数中获取 lowLimit1/highLimit1 值.我不成功的尝试之一在这里:
printfn "Type low OP number"
let lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number"
let highLimit = parseMe (Console.ReadLine())
let verifyingInputValues: unit =
let bodyOfWhileCycle _=
printfn "Type low OP number again"
let lowLimit1 = parseMe (Console.ReadLine())
printfn "Type high OP number again"
let highLimit1 = parseMe (Console.ReadLine())
()
fun _ -> highLimit - lowLimit
|> Seq.initInfinite
|> Seq.takeWhile ((>) 0)
|> Seq.iter bodyOfWhileCycle
verifyingInputValues
您似乎希望在 highLimit > lowLimit 时完成 while 循环,否则重复请求,并且可能稍后对它们进行处理。
在这种情况下,您需要一个 returns 元组 ( highLimit, lowLimit ) 而不是 unit () 的函数。通过将新状态作为参数传入,递归函数可以处理调用之间状态或 IO 的明显变化,没有可变性。
let fullParse: () -> int *int =
let parseHighLow again =
printfn "Type low OP number %s" again
let lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number %s" again
let highLimit = parseMe (Console.ReadLine())
highLimit, lowLimit
let rec verify (high, low) =
if high > low then high, low else verify (parseHighLow "again")
verify (parseHighLow "")
let (high, low) = fullParse ()
请注意 skip
而不是 take
,因为我们正在等待我们希望从用户那里收到的内容。我们想要的是一回事,所以我们将 head
函数应用于序列。总的来说,您的尝试很接近,但您的序列没有产生价值。
open System
let rec p name =
printfn "Input %s Value" name
let text = Console.ReadLine()
let (ok, i) = Int32.TryParse text
if ok then i else p name
let ps () =
Seq.initInfinite (fun _ -> p "High", p "Low")
|> Seq.skipWhile (fun (high, low) -> high <= low)
|> Seq.head
let (high, low) = ps ()
我一直在尝试将我的一个简单的 C# 控制台应用程序重新编写为纯函数式 F# 代码(如果可能的话)。到目前为止,我已经设法在 Seq 的帮助下将 while 块重写为“不可变”F#(类似于 Seq.initInfinite sequenceGenerator |> Seq.takeWhile 条件 |> Seq.iter bodyOfWhileCycle) - “F# for Fun and Profit”网站一直是我的灵感来源。
然而,这次我遇到了一个简单的 while 块,它在“可变”F# 中看起来如下(并且有效):
printfn "Type low OP number"
let mutable lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number"
let mutable highLimit = parseMe (Console.ReadLine())
let mutable myCondition = true
if highLimit > lowLimit then myCondition <- false
while myCondition do
printfn "Type low OP number again"
lowLimit <- parseMe (Console.ReadLine())
printfn "Type high OP number again"
highLimit <- parseMe (Console.ReadLine())
if highLimit > lowLimit then myCondition <- false
谁能帮我弄清楚如何将这个“可变”while-do 块重构为函数式样式? 我的尝试重构它不能按照我想要的方式工作——我不知道如何从 bodyOfWhileCycle 函数中获取 lowLimit1/highLimit1 值.我不成功的尝试之一在这里:
printfn "Type low OP number"
let lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number"
let highLimit = parseMe (Console.ReadLine())
let verifyingInputValues: unit =
let bodyOfWhileCycle _=
printfn "Type low OP number again"
let lowLimit1 = parseMe (Console.ReadLine())
printfn "Type high OP number again"
let highLimit1 = parseMe (Console.ReadLine())
()
fun _ -> highLimit - lowLimit
|> Seq.initInfinite
|> Seq.takeWhile ((>) 0)
|> Seq.iter bodyOfWhileCycle
verifyingInputValues
您似乎希望在 highLimit > lowLimit 时完成 while 循环,否则重复请求,并且可能稍后对它们进行处理。
在这种情况下,您需要一个 returns 元组 ( highLimit, lowLimit ) 而不是 unit () 的函数。通过将新状态作为参数传入,递归函数可以处理调用之间状态或 IO 的明显变化,没有可变性。
let fullParse: () -> int *int =
let parseHighLow again =
printfn "Type low OP number %s" again
let lowLimit = parseMe (Console.ReadLine())
printfn "Type high OP number %s" again
let highLimit = parseMe (Console.ReadLine())
highLimit, lowLimit
let rec verify (high, low) =
if high > low then high, low else verify (parseHighLow "again")
verify (parseHighLow "")
let (high, low) = fullParse ()
请注意 skip
而不是 take
,因为我们正在等待我们希望从用户那里收到的内容。我们想要的是一回事,所以我们将 head
函数应用于序列。总的来说,您的尝试很接近,但您的序列没有产生价值。
open System
let rec p name =
printfn "Input %s Value" name
let text = Console.ReadLine()
let (ok, i) = Int32.TryParse text
if ok then i else p name
let ps () =
Seq.initInfinite (fun _ -> p "High", p "Low")
|> Seq.skipWhile (fun (high, low) -> high <= low)
|> Seq.head
let (high, low) = ps ()