I'm trying to write function that receive [String]
which are names of files, String
which is the name of the files directory and *f
. The function will append to each file an integer in the end.
Here is what I got so far:
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
Assume that getVmFiles
is defined in my FileManipulation.dcl
file and in the context of this problem name
is "myDir"
and file list is ["hello.vm","Wiki.vm"]
For some reason, even that I got "finished" message on the screen, the files aren't modified. No matter what kind of integer I give to fopen
, even if its FWriteText
or FWriteData
its still doing nothing... also even if I'm using fwritec
or fwrites
with characters nothing happened.
What I'm missing here? Thanks a lot!
For some reason, even that I got "finished" message on the screen, the files aren't modified.
This is due to lazy evaluation. In appendNumInEndOfVmFiles
, the result of fclose
is not used, so fclose
is not evaluated. Because of this, fwritei
does not need to be evaluated either. You can fix this by adding a guard on ok2
:
# (ok2,_) = fclose file w
| not ok2 = abort "fclose failed\n"
= appendNumInEndOfVmFiles xs dirname w
However, the typical way to do this would be to rewrite the function to return a *f
instead of a String
, so that this unique value is not lost. As long as the result is used, then, the fwritei
is evaluated. You can potentially make the *f
argument strict (i.e. add a !
in front). This would make sure that it is evaluated before entering the function, so that all lingering file closes have been performed.
There are some more issues with your code:
Here, w
is used twice, which is illegal because it is of a strict type. You should use (ok2,w)
in the guard to continue with the same environment.
# (ok2,_) = fclose file w
= appendNumInEndOfVmFiles xs dirname w
The appendNumInEndOfVmFiles
needs to have a type context | FileSystem f
to resolve overloading of fopen
and fclose
.
Lastly:
... even if its
FWriteText
orFWriteData
...
Just so you know: the difference would be that the first would write the integer in an ASCII representation whereas the second would write it binary as 4 or 8 bytes (depending on the bitwidth of your system).