Search code examples
arraysalgorithmfunctional-programmingsmlsmlnj

Why does my while loop not terminate in this functional language?


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?


Solution

  • 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?