我正在尝试从包含
的文件中读取一个单词 test
(注意空白)。目标是使输出“测试”。这是我到目前为止所得到的:
val test = TextIO.openIn "test.txt"
fun stream_rdr stream = let fun get NONE = NONE
| get (SOME c) = SOME (c, stream)
in get (TextIO.input1 stream)
end
fun skip s = StringCvt.skipWS stream_rdr s
fun read_word stream = let val s = skip stream
in case StringCvt.splitl Char.isAlpha stream_rdr s
of ("", rest_s) => NONE
| (w, rest_s) => SOME (w, rest_s)
end
问题在于它不起作用。
Standard ML of New Jersey v110.76 [built: Sun Jun 29 03:29:51 2014]
- use "Read.ml" ;;
[opening Read.ml]
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val test = - : TextIO.instream
val stream_rdr = fn
: TextIO.instream -> (TextIO.elem * TextIO.instream) option
val skip = fn : TextIO.instream -> TextIO.instream
val read_word = fn : TextIO.instream -> (string * TextIO.instream) option
val it = () : unit
- read_word test ;;
val it = SOME ("est",-) : (string * TextIO.instream) option
-
我假设这与我定义stream_rdr
的方式有关,但我看不到定义它的好方法,以便它既取得进展又避免将被拒绝的字符放到skipWS
或splitl
。一般评论欢迎,但具体而言......
(char, instream) reader
在某处出现此行为?答案 0 :(得分:1)
麻烦的是,你的读者(巧妙地)违反了读者的语义。
在这种情况下,StringCvt.skipWS
会假设,如果它调用stream_rdr s
,然后返回SOME (c, s')
,则原始s
仍未修改。
也就是说,它可以尝试从字符源中读取一个字符,直到它遇到非空白字符,然后简单地返回第一个不返回空白字符的字符。但是,这是一个问题,因为调用stream_rdr
会修改s
。
要解决此问题,我建议您使用TextIO
stream_rdr
函数提供的字符阅读器,而不是构建自己的字符阅读器({{1} })。
答案 1 :(得分:1)
我最终接受了塞巴斯蒂安的建议并撰写了这篇文章:
val test = TextIO.openIn "test.txt"
fun scan_word reader state = let
val s = StringCvt.skipWS reader state
in case StringCvt.splitl Char.isAlpha reader s of
("", ns) => NONE
| (w, ns) => SOME (w, ns)
end
fun scan stream = TextIO.scanStream scan_word stream
它使用与之前相同的输入执行我想要的操作:
Standard ML of New Jersey v110.76 [built: Sun Jun 29 03:29:51 2014]
- [read.sml]
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
val test = - : TextIO.instream
val scan_word = fn : (char,'a) StringCvt.reader -> 'a -> (string * 'a) option
val scan = fn : TextIO.instream -> string option
val it = () : unit
- scan test ;;
val it = SOME "test" : string option
-
解决方案基于对内置Bool.scan
的阅读。如果你从Debian repos安装了mlton
,你会在/usr/lib/mlton/sml/basis/general/bool.sml
找到来源。相关部分包括在下面:
...
fun scan reader state =
case reader state of
NONE => NONE
| SOME(c, state) =>
case c of
#"f" => (case Reader.reader4 reader state of
SOME((#"a", #"l", #"s", #"e"), state) =>
SOME(false, state)
| _ => NONE)
| #"t" => (case Reader.reader3 reader state of
SOME((#"r", #"u", #"e"), state) =>
SOME(true, state)
| _ => NONE)
| _ => NONE
...