我知道由于Haskell IO - handle closed的错误,我不应该尝试重新阅读"{"filterBy"=>"name", "controller"=>"resource_name", "action"=>"index", "sortBy"=>"name"}"
例如,在下面:
stdin
第二个电话main = do
x <- getContents
putStrLn $ map id x
x <- getContents --problem line
putStrLn x
将导致错误:
x <- getContents
当然,我可以省略从test: <stdin>: hGetContents: illegal operation (handle is closed)
读取的第二行。
getContents
但这会成为性能/内存问题吗? GHC是否必须将main = do
x <- getContents
putStrLn $ map id x
putStrLn x
中的所有内容保存在主内存中?
我想第一次消耗stdin
时,GHC可以丢弃已经处理过的x
部分。因此从理论上讲,GHC只能使用少量的常量内存进行处理。但是,由于我们将再次使用x
(并且再次),似乎GHC不能扔掉任何东西。 (也不能再从x
读取。)
我对这些记忆含义的理解是否正确?如果有,是否有修复?
答案 0 :(得分:2)
是的,您的理解是正确的:如果您重复使用x
,ghc必须将其全部保留在内存中。
我认为可能的解决方法是懒散地消耗它(一次)。
假设您要将x
输出到多个输出句柄hdls :: [Handle]
。天真的方法是:
main :: IO ()
main = do
x <- getContents
forM_ hdls $ \hdl -> do
hPutStr hdl x
这会将stdin
读入x
,因为第一个hPutStr
遍历字符串(至少对于无缓冲的句柄,hPutStr
只是一个调用hPutChar
的循环}对于字符串中的每个字符)。从那时起,它将被保存在所有后续hdl
的内存中。
可替换地:
main :: IO ()
main = do
x <- getContents
forM_ x $ \c -> do
forM_ hdls $ \hdl -> do
hPutChar hdl c
这里我们转换了循环:不是迭代句柄(并且每个句柄迭代输入字符),我们迭代输入字符,对于每个字符,我们将它打印到每个句柄。
我还没有对它进行过测试,但是这种形式应该保证我们不需要大量的内存,因为每个输入字符c
只使用一次然后丢弃。