Чистый язык: добавить номер в конец файла, fwritei не работает - PullRequest
1 голос
/ 12 марта 2019

Я пытаюсь написать функцию, которая получает [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 Ответ

1 голос
/ 13 марта 2019

По какой-то причине, даже если на экране появилось сообщение «Готово», файлы не изменились.

Это связано с ленивой оценкой . В appendNumInEndOfVmFiles результат fclose не используется, поэтому fclose не оценивается. Из-за этого fwritei также не нужно оценивать. Вы можете исправить это, добавив охрану на ok2:

# (ok2,_) = fclose file w
| not ok2 = abort "fclose failed\n"
= appendNumInEndOfVmFiles xs dirname w

Однако типичным способом сделать это было бы переписать функцию, чтобы она возвращала *f вместо String, чтобы это уникальное значение не было потеряно. Пока используется результат, то fwritei оценивается. Вы можете потенциально сделать аргумент *f строгим (т.е. добавить ! впереди). Это позволит убедиться в том, что оно проверено перед входом в функцию, поэтому все закрытые файлы были выполнены.


Есть еще несколько проблем с вашим кодом:

  1. Здесь w используется дважды, что недопустимо, потому что это строгий тип. Вы должны использовать (ok2,w) в охране, чтобы продолжить в той же среде.

    # (ok2,_) = fclose file w
    = appendNumInEndOfVmFiles xs dirname w
    
  2. У appendNumInEndOfVmFiles должен быть контекст типа | FileSystem f для разрешения перегрузки fopen и fclose.


И наконец:

... даже если его FWriteText или FWriteData ...

Точно так же, как вы знаете: разница будет в том, что первый запишет целое число в представлении ASCII, тогда как второй запишет его в двоичном виде как 4 или 8 байтов (в зависимости от битовой пропускной способности вашей системы).

...