SML function that takes a filename and a list

允我心安 提交于 2019-12-11 17:11:47

问题


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:


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.



来源:https://stackoverflow.com/questions/46538706/sml-function-that-takes-a-filename-and-a-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!