【问题标题】:Clean language: append number in end of file, fwritei doesn't work干净的语言:在文件末尾附加数字,fwritei 不起作用
【发布时间】:2019-03-12 14:58:25
【问题描述】:

我正在尝试编写接收[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 提供什么样的整数,即使它的FWriteTextFWriteData 仍然什么也不做……即使我使用带有字符的fwritecfwrites 也没有任何反应。

我在这里缺少什么?非常感谢!

【问题讨论】:

    标签: functional-programming clean-language


    【解决方案1】:

    由于某种原因,即使我在屏幕上看到“完成”消息,文件也没有被修改。

    这是由于lazy evaluation。在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 来解决fopenfclose 的重载。


    最后:

    ...即使是FWriteTextFWriteData ...

    您知道:区别在于第一个将整数写入 ASCII 表示,而第二个将二进制写入 4 或 8 个字节(取决于系统的位宽)。

    【讨论】:

    • 谢谢。我修复了我的代码及其工作。你能解释更多关于| FileSystem f那里实际发生的事情吗?还有为什么我必须在警卫中使用(ok2,w)?我认为_ 已经足够好了。
    • @ZENir 抱歉,您的评论在我的收件箱中丢失了。 | FileSystem f 是一个类上下文,您可以在语言报告的section 6 中了解更多信息。简而言之,它包含了必要的函数fopenfclose,它们可以根据f有不同的实现。守卫是强制评估fclose。这有点类似于在类 C 语言中编写(true || f(x)) 时发生的情况:f(x) 不会被执行,因为它不需要评估||。你熟悉惰性求值吗?
    猜你喜欢
    • 2023-03-30
    • 1970-01-01
    • 2012-06-15
    • 2016-11-10
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2012-06-21
    • 2017-06-15
    相关资源
    最近更新 更多