Преобразование файлов в F #

Я только начинаю работать с F # и пытаюсь понять типичные иконы и эффективные способы мышления и работы.

Задача под рукой - простое преобразование файла с разделителями табуляции в раздел, разделенный запятой. Типичная строка ввода будет выглядеть так:

let line = "@ES#    01/31/2006 13:31:00 1303.00 1303.00 1302.00 1302.00 2514    0"

Я начал с кода цикла таким образом:

// inFile and outFile defined in preceding code not shown here

for line in File.ReadLines(inFile) do
    let typicalArray = line.Split '\t'
    let transformedLine = typicalArray |> String.concat ","   
    outFile.WriteLine(transformedLine)

Затем я заменил партию split/concat с одним Regex.Replace():

for line in File.ReadLines(inFile) do   
    let transformedLine = Regex.Replace(line, "\t",",")
    outFile.WriteLine(transformedLine)

И теперь, наконец, заменили цикл на конвейер:

File.ReadLines(inFile)
    |> Seq.map  (fun x -> Regex.Replace(x, "\t", ","))
    |> Seq.iter (fun y -> outFile.WriteLine(y))

  // other housekeeping code below here not shown

Пока все версии работают, окончательная версия кажется мне самой интуитивной. Это, как более опытный программист F # выполнил бы эту задачу?

Ответ 1

Я думаю, что все три версии прекрасно подходят, идиоматический код, который будут писать эксперты F #.

Я вообще предпочитаю писать код, используя встроенные функции языка (например, for loops и if), если они позволят мне решить проблему, которая у меня есть. Это необходимо, но я думаю, что использование их - хорошая идея, когда API требует императивного кода (например, outFile.WriteLine). Как вы упомянули, вы начали с этой версии (и я бы сделал то же самое).

Использование функций более высокого порядка тоже хорошо - хотя я бы это сделал, только если бы захотел написать преобразование данных и получить новую последовательность или список строк - это было бы удобно, если бы вы использовали File.WriteAllLines вместо того, чтобы писать линии один за другим. Хотя это можно было бы сделать, просто завернув вторую версию с помощью выражения последовательности:

let transformed = 
    seq { for line in File.ReadLines(inFile) -> Regex.Replace(line, "\t",",") }
File.WriteAllLines(outFilePath, transformed) 

Я не думаю, что есть какая-то объективная причина, чтобы предпочесть одну из версий. Моим личным стилистическим предпочтением является использование for и рефакторинг для выражения последовательности (если необходимо), но другие, скорее всего, не согласятся.