我最近做了Waterloo CCC,我觉得Haskell是回答这些类型问题的完美语言。我还在学习它。不过,我在输入方面有点挣扎。
以下是我正在使用的内容:
import IO
import System.Environment
import System.FilePath
…
main = do
name <- getProgName
args <- getArgs
input <- readFile $
if not (null args)
then head args
else dropExtension name ++ ".in"
let (k:code:_) = lines input
putStrLn $ decode (read k) code
如您所见,我正在从命令行给定文件路径或从j1.in
读取,例如,如果此程序被调用j1.hs
并编译为j1
。< / p>
我只对文件的前两行感兴趣,所以我使用模式匹配来获取这些行并将它们绑定到k
和code
,在本例中。然后我将k
读作整数并将其传递给我的decode
函数,并将其输出。
我想知道readFile
是否正在将整个文件加载到内存中,这很糟糕。但后来我开始思考,也许是因为Haskell是懒惰的,它只会读取前两行,因为这是后来要求的全部内容。我是对的吗?
此外,如果该代码示例中有任何内容可能更好或更具惯用性,请告知我们。
答案 0 :(得分:8)
readFile
函数读取文件并以字符串形式返回文件内容。与getContents
一样,该文件可以按需延迟读取。
所以是的,它只会读取文件的前两行(缓冲意味着它可能会在幕后阅读更多)。但这是readFile
的属性,而不是所有Haskell I / O函数。
对于I / O繁重的程序(例如Web服务器)来说,懒惰的I / O是一个坏主意,但它对于没有做太多I / O的简单程序很有效。
答案 1 :(得分:7)
是的,readFile
是懒惰的。如果你想明确它,你可以使用:
import Control.Monad (replicateM)
import System.IO
readLines n f = withFile f ReadMode $ replicateM n . hGetLine
-- in main
(k:code:_) <- readLines 2 filename
这将确保文件尽快关闭。
但你做得好的方式很好。
答案 2 :(得分:3)
readFile
懒惰地读取文件,因此除非您使用整个文件,否则它不会将整个文件读入内存。它通常不会完全读取前两行,因为它读取块,但它只会读取所需数量的块来查找第二个换行符。
答案 3 :(得分:2)
Haskell中的I / O通常不是懒惰的。但是,具体的readFile
函数是懒惰的。
其他人也说了同样的话。我还没有看到任何人指出的是,在程序结束或垃圾收集器运行之前,您打开的文件将不会关闭。这只意味着OS文件句柄可能会保持打开时间超过必要的时间。在你的程序中,这可能没什么大不了的。但在一个更复杂的项目中,它可能是。