Elements of ML Programming, 2nd Edition (ML97) |
fun xPrint1(0,s) = print(s) | xPrint1(n,s) = xPrint1(n-1, s^s); fun xPrint(n) = (xPrint1(n,"X"), print("\n") );Notice that xPrint1 counts down in its first argument, as it doubles the length of its second argument. Thus, when started as in the third line, with first argument n and a second argument consisting of one X, by the time the first argument is down to 0, the length of the second argument is 2^n. That is the string that gets printed at line 1.
Technically, we are not required to retain the returned instream. However, if we do not bind it to some identifier, such as IN here, the token representing the instream is lost forever.
closeIn(in1);This and subsequent solutions assume that structure TextIO is already open.
val newLine = inputLine(in3);
fun howMany1(infile,i) = if not (canInput(infile,i+1)) then i else howMany(infile,i+1); fun howMany(infile) = howMany1(infile, 0);Here, howMany1(infile,i) is an auxiliary that recursiively tries canInput with limits of i, i+1, and so on, until it finds that i for which there are exactly i characters waiting. A call by howMany to howMany1 with second argument 0 allows the exact number of waiting characters to be determined.
open TextIO; (* test if a character is white space *) fun white(" ") = true | white("\t") = true | white("\n") = true | white(_) = false fun getWord(file) = (* read one word *) if endOfStream(file) then "" else let val c = inputN(file,1) in if white(c) then "" else c^getWord(file) end; fun getList1(file) = (* read all words from an instream *) if endOfStream(file) then nil else getWord(file) :: getList1(file); (* read all words from a file given the file name *) fun getList(filename) = getList1(openIn(filename));Download this program
val OUT = openAppend("/usr/spool/mail/fred");This and the following solution assume that TextIO is already open.
output(out2, "super");
(* read digits until a nondigit and return their value assuming i is value of previously read digits of digits *) fun getInt(i,IN) = if not (isSome(TextIO.lookahead(IN))) then i (* end of file reached *) else let val c = valOf(TextIO.input1(IN)) in if c <= #"9" andalso c >= #"0" then (* c is a digit *) getInt(10*i+ord(c)-ord(#"0"),IN) else i end; (* print integer i in decimal *) fun putInt1(i,OUT) = if i<10 then TextIO.output(OUT, str(chr(i+ord(#"0")))) else ( putInt1(i div 10, OUT); (* print all but the last digit *) putInt1(i mod 10, OUT) (* print the last digit *) ); (* print i, surrounding multidigit numbers by parens *) fun putInt(i,OUT) = if i<10 then putInt1(i,OUT) else ( TextIO.output(OUT,"("); putInt1(i,OUT); TextIO.output(OUT,")") ); (* convert i to a sequence of base-b digits and print *) fun convert1(i,b,OUT) = if i<b then putInt(i,OUT) else ( convert1(i div b, b, OUT); putInt(i mod b, OUT) ); (* read i and b and print i in base b *) fun convert(IN,OUT) = let val i = getInt(0,IN); val b = getInt(0,IN) in convert1(i,b,OUT) end;Download this program