TextIO.scanStream is wrong
Henry Cejtin
henry@sourcelight.com
Mon, 11 Sep 2000 22:49:36 -0500
Ok, I have been thinking about this for a bit, and I finally realized that
something is REALLY wrong with MLton TextIO. For a concrete example,
consider the following code:
fun getSome (n, chreader, state) =
if n = 0
then ([], state)
else case chreader state of
NONE => ([], state)
| SOME (ch, state') =>
let val (ac, state'') = getSome (n - 1,
chreader,
state')
in (ch::ac, state'')
end
fun fake chreader state =
let val (bef, state') = getSome (10, chreader, state)
val (after, state'') = getSome (10, chreader, state')
val (bef', state''') = getSome (10, chreader, state)
val bef = String.implode bef
val after = String.implode after
val bef' = String.implode bef'
in print ("1st = |" ^ bef ^ "|\n");
print ("2nd = |" ^ after ^ "|\n");
print ("3rd = |" ^ bef' ^ "|\n");
NONE
end
;
val z = TextIO.openIn "/etc/passwd"
val _ = TextIO.scanStream fake z
val _ = TextIO.scanStream fake z
If you run this using SML/NJ, you get the `correct' answer (one I think is
right):
1st = |chars 0-9 of /etc/passwd|
2nd = |chars 10-19 of /etc/passwd|
3rd = |chars 0-9 of /etc/passwd|
1st = |chars 0-9 of /etc/passwd|
2nd = |chars 10-19 of /etc/passwd|
3rd = |chars 0-9 of /etc/passwd|
If you run it under MLton you get
1st = |chars 0-9 of /etc/passwd|
2nd = |chars 10-19 of /etc/passwd|
3rd = |chars 0-9 of /etc/passwd|
1st = |chars 20-29 of /etc/passwd|
2nd = |chars 30-39 of /etc/passwd|
3rd = |chars 20-29 of /etc/passwd|
Don't get me wrong: I think that the TextIO.scanStream interface is slightly
goofy (i.e., I can't off hand think of a reasonable way to make it work
fast), but what we have is clearly wrong.