什么是从stdin读取的最佳方式?

Chr*_*uer 1 f# stdin console.readline

我目前正在努力学习F#,我正在使用编码作为编程测验的来源.

大多数的quizess涉及从stdin读取一些值,就像stdin上的前十个值将是int,接下来的五个将是字符串.

目前,我正在使用此功能来读取数据,但感觉非常"un-f#".

let N = 5
let Reader i =
    Console.In.ReadLine()

let words = [0..N-1] |> Seq.map Reader 
Run Code Online (Sandbox Code Playgroud)

Fyo*_*kin 7

从评论中可以看出,你最喜欢"F#-native"(我们称之为"惯用的F#")从控制台读取的方式.

你有什么是惯用的,除了函数,按照惯例,通常以小写字符开头:

let reader i = Console.ReadLine()
Run Code Online (Sandbox Code Playgroud)

另外,由于您没有使用参数,因此您无需为其命名:

let reader _ = Console.ReadLine()
Run Code Online (Sandbox Code Playgroud)

如果函数足够小,您可以匿名编写内联函数:

let words = [0..N-1] |> Seq.map (fun _ -> Console.ReadLine())
Run Code Online (Sandbox Code Playgroud)

此外,由于您实际上并未使用索引,因此可以将列表声明为1..N而不是0..N-1.看起来更清洁.

最后,F#提供了非常方便的列表推导,您可以使用它们来实现更好的可读性:

let N = 5
let words = [for _ in 1..N -> Console.ReadLine()]
Run Code Online (Sandbox Code Playgroud)

  • 请注意 F# 中的特殊 `stdin` 值,它可以在此处用作快捷方式:`stdin.ReadLine()`。还有一个`stdout.WriteLine()`。关于这些的一个好处是你甚至不需要“打开系统”。 (4认同)

Car*_*Dev 5

如果我必须读取给定类型的给定数量,我会写类似的东西

open System

let read parser =
    Seq.initInfinite (fun _ -> Console.ReadLine())
    |> Seq.choose (parser >> function true, v -> Some v | _ -> None)
Run Code Online (Sandbox Code Playgroud)

然后可以使用

let ints = read Int32.TryParse
let ``ten floats`` = read Double.TryParse |> Seq.take 10
Run Code Online (Sandbox Code Playgroud)

请注意,如果seq多次使用,ReadLine()则再次调用:

let anInt = ints |> Seq.take 1
printfn "%A" anInt
printfn "%A" anInt // need to input an int again
Run Code Online (Sandbox Code Playgroud)

这可以通过使用例如ListSeq.cache.

对于永不失败的字符串,请使用

let strings = read (fun s -> true, s)
Run Code Online (Sandbox Code Playgroud)

如果您有最低长度要求:

let potentialPasswords = read (fun s -> s.Length > 10, s)
Run Code Online (Sandbox Code Playgroud)