3

我目前正在尝试更好地学习 F#,并且我正在使用 codingame 作为编程测验的来源。

大多数测验涉及从标准输入读取一些值,例如标准输入上的前十个值将是整数,接下来的五个将是字符串。

目前,我正在使用这个函数来读取数据,但感觉很“un-f#”。

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

let words = [0..N-1] |> Seq.map Reader 
4

2 回答 2

9

从评论中,很明显您希望从控制台读取最“F#-native”(我们称之为“惯用 F#”)的方式。

你所拥有的已经足够惯用了,除了函数,按照惯例,通常以小写字符开头:

let reader i = Console.ReadLine()

另外,由于您没有使用该参数,因此您不必为其命名:

let reader _ = Console.ReadLine()

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

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

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

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

let N = 5
let words = [for _ in 1..N -> Console.ReadLine()]
于 2016-12-01T21:08:31.393 回答
6

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

open System

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

然后可以使用

let ints = read Int32.TryParse
let ``ten floats`` = read Double.TryParse |> Seq.take 10

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

let anInt = ints |> Seq.take 1
printfn "%A" anInt
printfn "%A" anInt // need to input an int again

可以使用 egList或来处理Seq.cache

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

let strings = read (fun s -> true, s)

如果您有最小长度要求:

let potentialPasswords = read (fun s -> s.Length > 10, s)
于 2016-12-01T23:12:57.697 回答