Чистый язык: добавить номер в конец файла, fwritei не работает
Я пытаюсь написать функцию, которая получает [String]
которые являются именами файлов, String
который является именем каталога файлов и *f
, Функция добавит к каждому файлу целое число в конце.
Вот что я получил так далеко:
import StdEnv
import StdFile
import FileManipulation
appendNumInEndOfVmFiles :: [String] String *f -> String
appendNumInEndOfVmFiles [] dirname w = "finished"
appendNumInEndOfVmFiles [x:xs] dirname w
# path = dirname +++ "\\\\" +++ x
# (ok,file,files) = fopen path FAppendText w
# file = fwritei 12 file
# (ok2,_) = fclose file w
= appendNumInEndOfVmFiles xs dirname w
Start w
// 1. Receive name of directory from the user.
# (io,w) = stdio w // open stdio
# io = fwrites "Enter name of directory:\n" io // ask for name
# (name,io) = freadline io // read in name
# name = name % (0, size name - 2) // remove \n from name
# (ok,w) = fclose io w // close stdio
| not ok = abort "Couldn't close stdio" // abort in case of failure
// 2. Get a list of all file names in that directory.
# (dir,w) = getDirectoryContents (RelativePath [PathDown name]) w
# fileList = getNamesOfFilesInDirectory (getEntriesList dir)
= appendNumInEndOfVmFiles (getVmFiles fileList) name w
Предположим, что getVmFiles
определяется в моем FileManipulation.dcl
файл и в контексте этой проблемы name
является "myDir"
и список файлов ["hello.vm","Wiki.vm"]
По какой-то причине, даже если я получил "готовое" сообщение на экране, файлы не изменились. Независимо от того, какое целое число я даю fopen
, даже если его FWriteText
или же FWriteData
все еще ничего не делает... даже если я использую fwritec
или же fwrites
с персонажами ничего не случилось.
Что мне здесь не хватает? Большое спасибо!
1 ответ
По какой-то причине, даже если я получил "готовое" сообщение на экране, файлы не изменились.
Это связано с ленивой оценкой. В appendNumInEndOfVmFiles
, результат fclose
не используется, так fclose
не оценивается. Из-за этого, fwritei
оценивать не нужно. Вы можете исправить это, добавив охрану на ok2
:
# (ok2,_) = fclose file w
| not ok2 = abort "fclose failed\n"
= appendNumInEndOfVmFiles xs dirname w
Однако типичным способом сделать это было бы переписать функцию, чтобы вернуть *f
вместо String
, так что это уникальное значение не теряется. Пока результат используется, то fwritei
оценивается. Вы можете сделать *f
строгий аргумент (т.е. добавить !
спереди). Это будет гарантировать, что оно будет оценено перед входом в функцию, чтобы все закрытые файлы были выполнены.
Есть еще несколько проблем с вашим кодом:
Вот,
w
используется дважды, что недопустимо, потому что это строгий тип. Вы должны использовать(ok2,w)
в карауле, чтобы продолжить в той же среде.# (ok2,_) = fclose file w = appendNumInEndOfVmFiles xs dirname w
appendNumInEndOfVmFiles
должен иметь контекст типа| FileSystem f
разрешить перегрузкуfopen
а такжеfclose
,
И, наконец:
... даже если его
FWriteText
или жеFWriteData
...
Просто чтобы вы знали: разница будет в том, что первый запишет целое число в представлении ASCII, тогда как второй запишет его в двоичном виде как 4 или 8 байтов (в зависимости от битовой пропускной способности вашей системы).