更新:Frege 最新版本中的 I/O 支持
从 3.21.80 版本开始,我们在标准库中提供了更好的 I/O 支持:
- 运行时提供
stdout
和stderr
(缓冲,UTF8 编码java.io.PrintWriters
环绕java.lang.System.out
和java.lang.System.err
)和stdin
(UTF8 解码java.io.BufferedReader
环绕java.lang.System.in
)
- 函数
print
, println
, putStr
,putChar
写入stdout
getChar
并在文件末尾getLine
读取stdin
并抛出异常。
- Java 类的 Frege 等价物
PrintWriter
在BufferedWriter
module 中定义Java.IO
,它是自动导入的。有了这个,更多的基本功能得到了支持。例如,BufferedReader.readLine
返回类型为IO (Maybe String)
并且确实通过返回来表示文件结束,就像在这种情况下Nothing
返回的 Java 对应项一样。null
这是一个实现基本 grep 的简短示例程序:
--- A simple grep
module examples.Grep where
--- exception thrown when an invalid regular expression is compiled
data PatternSyntax = native java.util.regex.PatternSyntaxException
derive Exceptional PatternSyntax
main [] = stderr.println "Usage: java examples.Grep regex [files ...]"
main (pat:xs) = do
rgx <- return (regforce pat)
case xs of
[] -> grepit rgx stdin
fs -> mapM_ (run rgx) fs
`catch` badpat where
badpat :: PatternSyntax -> IO ()
badpat pse = do
stderr.println "The regex is not valid."
stderr.println pse.getMessage
run regex file = do
rdr <- utf8Reader file
grepit regex rdr
`catch` fnf where
fnf :: FileNotFoundException -> IO ()
fnf _ = stderr.println ("Could not read " ++ file)
grepit :: Regex -> BufferedReader -> IO ()
grepit pat rdr = loop `catch` eof `finally` rdr.close
where
eof :: EOFException -> IO ()
eof _ = return ()
loop = do
line <- rdr.getLine
when (line ~ pat) (println line)
loop
由于 Frege 还很新,尽管在最基本的领域(如 Lists 和 Monads)已经取得了进展,但承认仍然缺乏对库的支持。
此外,虽然意图是与 Haskell 有高度的兼容性,尤其是在 IO 系统和一般在低级系统相关的主题中,但存在一种张力:我们是宁愿走 Java 路还是真的尝试模仿 Haskell 的方式(这又明显受到标准 C/POSIX 库中可用内容的影响)。
反正 IO 的东西可能是 Frege 库最不发达的领域,可惜了。这也是因为相对容易快速地为少数 Java 方法编写本机函数声明,这是一种特别的方式,而不是花时间开发一个完善的库。
此外,目前还不存在 Read 类。作为解决此问题之前的替代品,String 类型具有解析所有数字类型的函数(基于 Java parseXXX() 方法)。
(旁注:因为我的日子也只有 24 小时,而且我有一个家庭、一条狗和一份工作要关心,所以我很高兴有更多的贡献者来帮助改进 Frege 系统。)
关于您的代码:是的,我认为通过 Reader 和 Writer 接口进行所有基于字符的 I/O 是正确的。您的示例还表明,需要获得标准输入阅读器的便利功能。标准输出编写器也是如此。
但是,当您需要阅读超过 1 行时,我肯定会在主函数中创建阅读器并将其传递给输入处理操作。