将字符列表拆分为单词列表

Split list of characters into list of words

我目前正在学习 SML 函数式语言,我正在尝试制作一个接受字符列表的函数,然后在找到白色 space 时搜索列表中的任何白色 space ] 它连接白色 space 之前的字符以在之后形成一个字符串 returns 由白色 spaces.

分割的字符组成的字符串列表

这是我的代码,但它有问题,编译器说在 eof 处有错误!

fun sepWords ([]) = []
  | sepWords (x :: xs) =
    let 
      val word = "" 
      val list
      sepWords (xs)
    in 
      if (Char.isSpace (x)) then (word = "")
      else (word ^ x)
      word :: list
    end;
  1. val listsepWords (xs) 行有语法错误。也许你打算写 val list = sepWords (xs)if ...word :: list 行也存在语法错误。我不确定这里的意图是什么,但也许你认为 word :: list 会产生将 'word' 添加到 'list'?

  2. 的副作用
  3. 您的 if ... 中存在类型错误,因为 'then' 分支的表达式 word = "" 的类型为 bool 并且 'else' 分支具有类型为 string 的表达式 word ^ x。 if-then-else 必须在每个分支上具有相同的类型,类型检查器才能接受该程序。

  4. 与其创建类型为 char list -> string list 的函数,不如创建类型为 string -> string 的函数列表?如果这样做,您甚至可以通过跟踪原始字符串中的字符索引来避免将 string 转换为 char list 的中间步骤(例如,通过使用 substring 类型)。

    该函数的一个好名字可以是 'words'.

  5. 您尚未定义多个空格连续出现时的行为。 words "hello world" 应该产生 ["hello", "world"] 还是 ["hello", "", "world"]

  6. 实际上有内置的库函数可以做到这一点:

    - String.tokens Char.isSpace "hello  world";
    > val it = ["hello", "world"] : string list
    
    - String.fields Char.isSpace "hello  world";
    > val it = ["hello", "", "world"] : string list
    
  7. 首先将 string 转换为 char list 的替代方法是列表递归的一个很好的练习,即使该策略不是很有效。您可以通过解决从输入中提取单个单词以及字符串的其余部分来解决此问题:

    fun firstWord [] = ([], [])
      | firstWord (c::cs) =
        if Char.isSpace c
        then ([], cs)  (* throw away the space c *)
        else case firstWord cs of
               (fw, remainder) => (c::fw, remainder)
    

    你可以这样称呼它:

    - firstWord (explode "hello  world");
    > val it =
        ([#"h", #"e", #"l", #"l", #"o"], [#" ", #"w", #"o", #"r", #"l", #"d"])
            : char list * char list
    

    并且只要余数不为空就可以递归调用:

    fun words [] = []
      | words cs =
        let val (fw, remainder) = firstWord cs
        in implode fw :: words remainder end
    

    并使用这个:

    - allWords (explode "hello  world");
    > val it = ["hello", "", "world"] : string list