I'm trying to build a standard ML program using both imperative and functional concepts, and write the contents to a file. But my while loop doesn't seem to terminate and instead prints the same value continuously.
fun writeImage image filename =
let val ap = TextIO.openOut filename
val (w,h) = size image
val row = ref 0
val stringToWrite = "";
in
while !row < h do
TextIO.output(ap,"A");
row := !row + 1;
TextIO.closeOut ap
end;
If I remove the first line after the while loop, the loop terminates. But if I include TextIO.output(ap,"A");
, it doesn't. Why is this the case?
Let's write your program with correct indentation, and then it becomes clear where the mistake is:
...
while !row < h do
TextIO.output(ap,"A");
row := !row + 1;
TextIO.closeOut ap
...
You loop forever because the increment is outside of the body of the loop.
You intended to write this:
...
while !row < h do (
TextIO.output(ap,"A");
row := !row + 1
);
TextIO.closeOut ap
...
right?
I have long made a study of how people come to make mistakes when programming. I am curious to know how you came to make this mistake. If you believed that ;
binds stronger than while
then why did you believe that the TextIO.closeOut ap
was after the loop? Surely if your belief was that the ;
binds the increment to the loop then the ;
should bind it to the loop as well. Did you perhaps think that ML is a language like Python, where the looping constructs use the whitespace as a guide to the extent of the body?
What are your beliefs about ;
in ML more generally? Do you think of ;
as a statement terminator, as it is in C-like languages? Or do you think of it as an infix sequencing operation on side-effecting expressions?
What was your thought process here, and how could the tooling have made it easier for you to solve your problem without having to ask for help?