Чистый язык: добавить номер в конец файла, fwritei не работает

#functional-programming #clean-language

#функциональное программирование #чистый язык

Вопрос:

Я пытаюсь написать функцию, которая получает, [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 failedn"
= appendNumInEndOfVmFiles xs dirname w
  

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


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

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

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


Наконец:

… даже если это FWriteText или FWriteData

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

Комментарии:

1. Спасибо. Я исправил свой код и его работоспособность. можете ли вы подробнее объяснить об этом, | FileSystem f что там на самом деле происходит? также почему я должен использовать (ok2,w) в guard? Я думал, _ этого достаточно.

2. @ZENir извините, ваш комментарий затерялся в моем почтовом ящике. | FileSystem f это контекст класса, вы можете прочитать больше об этом в разделе 6 отчета о языке. Короче говоря, он содержит необходимые функции fopen и fclose , которые могут иметь разные реализации в зависимости от f . Защита заключается в принудительной оценке fclose . Это несколько похоже на то, что происходит в C-подобном языке, когда вы пишете (true || f(x)) : f(x) не выполняется, потому что это не требуется для оценки || . Вы знакомы с отложенным вычислением?