SML function that takes a filename and a list

2019-08-16 17:27发布

I want to write a function that takes a filename as a string and a list of pairs of characters. This function must open the named file, read the contents of the file, and echo the characters to the screen. Any occurrence of a character in the first position of a pair must be echoed as the character in the second position of the pair. For example, an invocation such as fileSubst "inputFile" [(#"a", #"b"), (#"b", #"z")] will echo the contents of inputFile with all occurrences of the character a replaced by the character b and all occurrences of the character b replaced by character z.

    fun fileSubst (fileName : string, []) = nil
  | fileSubst (fileName, (a,b)::cs) = let 
    val stream = TextIO.openIn fileName    
     TextIO.input1 = fileSubst (fileName,cs) in if isSome a 
    then print(Char.toString(a)) else TextIO.print end ;

1条回答
甜甜的少女心
2楼-- · 2019-08-16 18:18

As @molbdnilo suggest, split this into several functions that might be useful in other contexts. You could divide this into one function that reads the file's content into a string,

fun readFile fname =
    let val fd = TextIO.openIn fname
        val contents = TextIO.inputAll fd
        val _ = TextIO.closeIn fd
    in contents end

a function that searches for the right mapping in a list of pairs of characters,

fun lookup [] needle = NONE
  | lookup ((key,value)::haystack) needle =
    if needle = key then SOME value else lookup haystack needle

a variation of this function that returns the key as a default value,

fun lookupDefault haystack needle =
    Option.getOpt (lookup haystack needle, needle)

and a function that maps each character in a string to another one,

fun subst mapping = String.map (lookupDefault mapping)

You can then compose those to get one that operates on files. I'm not sure I would assume that a function call fileSubst "foo.txt" might read the file's content, perform the substitution and print the result to screen. Why wouldn't it write it back to file or return it as a string?

Since there are so many things you can do with a file's content, you could also make a more generic file handling function,

fun withFile fname f =
    let val fd = TextIO.openIn fname
        val contents = TextIO.inputAll fd
        val _ = TextIO.closeIn fd
    in f contents end

Then for example,

- withFile "helloworld.txt" (print o subst [(#"l", #"L")]);
HeLLo, WorLd!

By making generically useful functions you don't have to populate your library with highly specialized functions that are likely not going to be re-used much anyways.

查看更多
登录 后发表回答