Я читал много сообщений здесь, которые очень помогли мне с моей проблемой, но все мои попытки не принесли плодов.F # чтение csv по строкам асинхронно с изменяемым объектом
Услышь мой код:
первая функция (Чтение файла для использования построчно)
let readLines filePath = System.IO.File.ReadLines(filePath)
Вторая функция (обработка линии) EDIT: ошибка опечатка Я забыл строку строки в моем первый пост
let processLine (line:string) (myobj:MYOBJ) =
// .... some processing
myobj // I return the object modified
Теперь я хотел бы, чтобы обработать файл асинхронно с этим (попытка не работает! но цель объяснить то, что я хотел бы,)
let processAll file =
async { // some processing
let mutable obj = new MYOBJ()
readLines file
|> Seq.iter (fun l -> let obj = proceesLine l) // I would like to modify the object after each Line
}
Я пробовал использовать ref и! для обработки мутации, но не придумал чистого и ясного решения. Что было бы лучшей практикой кода в этом случае?
ВОЗМОЖНОЕ РЕШЕНИЕ: спасибо за вашу драгоценную помощь, здесь возможно два решения
первого решение:
let readL (file:string) =
async {
let mutable myobj = ref(new MYOBJ())
use sr = new StreamReader(file)
while not sr.EndOfStream do
let line = sr.ReadLine()
myobj := proccesLine line !myobj
()
sr.Close()
}
второго Solutio: (с использованием CSVReader Library)
let readL (file:string) =
async {
let myobj = new MYOBJ()
use sr = new CsvReader(new StreamReader(file),false)
let fcount = sr.FieldCount
let data : string array = Array.zeroCreate fcount
let rec readLinloop (readNext, str:CsvReader, obj:MYOBJ) =
match readNext with
| false ->()
| true -> sr.CopyCurrentRecordPartTo(data,0)
let obj = processLine data obj
readL(str.ReadNextRecord(), str, obj)
readLinLoop(sr.ReadNextRecord(),sr, myobj)
sr.Dispose()
}
сейчас , Я все еще хотел знать, возможно ли иметь встроенную функцию, которая возвращает что-то иное, чем тип единицы, используя Seq.iter. Код будет легче читать.
EDIT: третье решение, предложенное iljarn, что решается вопрос
let processAll file =
async { (MYOBJ(), readLines file) ||> Seq.fold processLine }
Ваш вопрос нет смысла - вы говорите, что 'processLine' берет' MYOBJ', но вы фактически передаете ему строку, в этом случае ваш код эквивалентен 'let obj = readLines file>> Seq.last |> processLine'. В любом случае, посредством вашего _description_ того, что вы хотите, 'ref' - это путь; покажите свою попытку использования 'ref', и это, вероятно, тривиально можно исправить. – ildjarn
Почему, по вашему мнению, это связано с асинхронностью? – Daniel
@ildjarn: thx для комментария, я забыл добавить строковый параметр в функцию. Возможно, я был недостаточно ясен: мне нужно обработать файл, прочитав каждую строку и изменив myobj перед тем, как перейти к следующей строке. В основном, я считаю, что мой вопрос эквивалентен спросить, возможно ли иметь встроенную функцию, возвращающую что-то другое, кроме единицы после Seq.iter – Anass