F# 从Console.In读取函数返回以前的值
为了学习F#我正试图解决密码问题F# 从Console.In读取函数返回以前的值,f#,F#,为了学习F#我正试图解决密码问题 从Console.In.ReadLine()读取8个数字 应打印最高编号的索引 重复8次 下面的代码适用于第一次运行,但对于不同的输入,在第一次循环后似乎给出了完全相同的结果。 在与数组交互的情况下运行idxWithHighestValue函数,而不是从控制台读取,可以获得所需的结果 预期行为: [9,8,7,6,5,4,3,2]=>0 [0,8,7,6,5,4,3,2]=>1 实际行为: [9,8,7,6,5,4,3,2]=>0 [0,8,7,6,5,4,
- 从Console.In.ReadLine()读取8个数字
- 应打印最高编号的索引
- 重复8次
在与数组交互的情况下运行idxWithHighestValue函数,而不是从控制台读取,可以获得所需的结果 预期行为:
[9,8,7,6,5,4,3,2]=>0
[0,8,7,6,5,4,3,2]=>1 实际行为:
[9,8,7,6,5,4,3,2]=>0
[0,8,7,6,5,4,3,2]=>0
open System
let highestMountain =
let readEightInputs =
let readlines n = Array.init n (fun _ -> Console.In.ReadLine() |> int)
readlines 8
let idxWithHighestValue list =
list
|> Seq.mapi (fun i v -> i, v)
|> Seq.maxBy snd
|> fst
idxWithHighestValue readEightInputs
(* game loop *)
while true do
(* Write an action using printfn *)
(* To debug: Console.Error.WriteLine("Debug message") *)
printfn "%i" highestMountain(* The index of the mountain to fire on. *)
()
我的readEightInputs函数有什么问题吗?问题是,
最高峰
只是一个int
值,但您希望它是一个读取控制台输入并返回int
的函数,即它的类型签名应该是unit->int
,而不是int
。只需将()
(单位)添加到声明中,它就成为了一个可以调用的函数,而不仅仅是一个要计算一次的值。然后可以在循环中调用该函数:
let highestMountain () =
let readEightInputs =
let readlines n = Array.init n (fun _ -> Console.In.ReadLine() |> int)
readlines 8
let idxWithHighestValue list =
list
|> Seq.mapi (fun i v -> i, v)
|> Seq.maxBy snd
|> fst
idxWithHighestValue readEightInputs
while true do
let result = highestMountain()
printfn "%i" result (* The index of the mountain to fire on. *)
()
在您的示例中,highestMountain
中的代码只计算一次,以获得其最终的int
值,无需再次计算;就F#而言,它的价值永远不会改变。使它成为函数意味着您可以根据需要多次调用它以获得不同的输入
这里有一种通过提取通常有用的函数来重构代码的方法:
let readLines count = // int -> string[]
[| for _ in 1 .. count -> Console.ReadLine() |]
let maxValueIndex source = // seq<'a> -> int
source
|> Seq.mapi (fun i v -> i, v)
|> Seq.maxBy snd
|> fst
while true do
let highMountainIdx = readLines 8 |> Seq.map int |> maxValueIndex
printfn "%i" highMountainIdx
()
// int -> int
let highestMountain = readLines >> Seq.map int >> maxValueIndex
现在,这是一个函数,它获取大量(要读取的山脉)并返回最大山脉的索引,称为like
printfn“%i”(最高山8)
。请注意,highestMountain
定义没有明确的参数,但它是一个函数,因为它是通过
运算符由其他函数组成的。它的参数与第一个函数readLines
相同,返回类型与最后一个函数maxValueIndex
相同。这是因为中间(curried)函数Seq.map int
与readLines
的输出和maxValueIndex
的输入兼容Taylor Wood已经指出highestMountain
只是一个整数值,而不是一个函数。我只想提一下,您会问“我的readEightInputs函数有什么问题吗?”,但事实上,在您向我们展示的代码中,readEightInputs
也是一个值,而不是一个函数。在F#中,这是一个值:
let name = (series of expressions)
这是一个函数:
let name parameter = (series of expressions)
如果名称后面至少有一个参数,即使该参数是“单位”值()
,那么它是一个函数,=字符后面的一系列表达式将在每次调用该函数时求值。如果没有参数,则该值只计算一次。(顺便说一句,“unit”值()
非常有用。请将此值视为空元组:空元组只有一个可能的值,因此该类型称为unit
,因为它只能有一个)
我还要提到一件事:你的readeightinput
值,即使你把它变成了一个函数,看起来也有点傻。为什么不直接使用readlines
函数呢?readlines
函数是一个好的、有用的函数。您可以将该行写成idxWithHighestValue(readlines 8)
,而不是idxWithHighestValue(readlines 8)
。瞧:现在如果你在以后的练习中不得不读十行,你可以调用readlines10
。代码重用是一件好事。aha,没有预期的错误。Thx:)Thx了解更多信息。我在这里真正学到了新东西:)我读过关于这个单元的书,但直到现在我才真正了解它。Thx:)注册readEightLines:你可能是对的,我只是在试验我应该把它推多远