F#写入文件更改返回类型的行为

vil*_*asv 4 f# cntk

我有以下函数将csv文件转换为特定的txt模式(由CNTKTextFormat Reader预期):

open System.IO
open FSharp.Data;
open Deedle;

let convert (inFileName : string) = 
    let data = Frame.ReadCsv(inFileName)
    let outFileName = inFileName.Substring(0, (inFileName.Length - 4)) + ".txt"
    use outFile = new StreamWriter(outFileName, false)
    data.Rows.Observations
    |> Seq.map(fun kvp ->
        let row = kvp.Value |> Series.observations |> Seq.map(fun (k,v) -> v) |> Seq.toList
        match row with
        | label::data ->
            let body = data |> List.map string |> String.concat " "
            outFile.WriteLine(sprintf "|labels %A |features %s" label body)
            printf "%A" label
        | _ ->
            failwith "Bad data."
    )
    |> ignore
Run Code Online (Sandbox Code Playgroud)

奇怪的是,输出文件在F#交互式面板中运行后为空,并且printf根本不会打印.

如果我删除ignore以确保有正在处理的实际行(通过返回一个空的seq证明),而不是我得到的空文件:

val it : seq<unit> = Error: Cannot write to a closed TextWriter.

之前,我正在声明StreamWriter使用let和手动处理它,但我也生成了空文件或只有几行(比如说成千上万).

这里发生了什么?另外,如何修复文件写入?

Lee*_*Lee 7

Seq.map返回一个惰性序列,在迭代之前不会对其进行求值.您目前没有迭代它,convert因此没有处理任何行.如果你返回Seq<unit>并在外面迭代它convert,那么outFile就已经关闭了,这就是你看到异常的原因.

您应该使用Seq.iter:

data.Rows.Observations
    |> Seq.iter (fun kvp -> ...)
Run Code Online (Sandbox Code Playgroud)