Sml 从溪流中读书
我正试图从一个包含Sml 从溪流中读书,sml,Sml,我正试图从一个包含 test (注意空格)。目标是获得输出“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) en
test
(注意空格)。目标是获得输出“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\u rdr
有关,但我看不到一个好的定义方法,以便它既能取得进展,又能避免将被拒绝的字符丢弃到skipWS
或splitl
。欢迎发表一般性意见,但具体而言
(char,instream)读卡器
具有这种行为问题是,您的读者(微妙地)违反了读者的语义 在这种情况下,
StringCvt.skipWS
假设,如果它调用stream\u rdr s
,并返回SOME(c,s')
,则原始的s
保持不变
也就是说,它可以尝试从字符源读取一个字符,直到它遇到一个非空白字符,然后只返回第一个不返回空白字符的字符。但是,在您的情况下,这是一个问题,因为调用stream\u rdr
会修改s
为了解决这个问题,我建议使用
TextIO
函数提供的字符读取器,而不是构建自己的字符读取器(stream\rdr
)。我接受了Sebastian的建议,写了以下内容:
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
-
该解决方案基于对内置程序的读取。如果您从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
...
特别是,
Bool
的默认扫描器具有指导意义。如果您从Debian repos安装了mlton
,您可以在/usr/lib/mlton/sml/basis/general/bool.sml