试图从字符列表中获取第一个单词

时间:2015-10-25 15:25:09

标签: sml smlnj

我有一个字符列表[#"h", #"i", #" ", #"h", #"i"],我希望从中得到第一个字(每个空格前的第一个字符序列)。

我写了一个函数,它给了我这个警告:

  

stdIn:13.1-13.42警告:因价值而未输入广义类型   限制被实例化为虚拟类型(X1,X2,...)

这是我的代码:

fun next [] = ([], [])
   | next (hd::tl) = if(not(ord(hd) >= 97 andalso ord(hd) <= 122)) then ([], (hd::tl))
       else
         let
           fun getword [] = [] | getword (hd::tl) = if(ord(hd) >= 97 andalso ord(hd) <= 122) then [hd]@getword tl else [];
         in
           next (getword (hd::tl))
         end;

编辑:

预期的输入和输出

next [#"h", #"i", #" ", #"h", #"i"] => ([#"h", #"i"], [#" ", #"h", #"i"]) 

有人可以帮我解决这个问题吗?谢谢!

1 个答案:

答案 0 :(得分:1)

此功能已存在于标准库中:

val nexts = String.tokens Char.isSpace
val nexts_test = nexts "hi hi   hi" = ["hi", "hi", "hi"]

但是如果你要构建这样一个函数,似乎有时会返回([], []),有时会返回一个列表。通常在递归函数中,您可以通过执行以下操作来构建结果: c :: recursive_f cs,但这假设您的函数返回单个列表。相反,如果它返回一个元组,你突然必须使用例如解压缩这个元组。 let-expression中的模式匹配:

let val (x, y) = recursive_f cs
in (c :: x, y + ...) end

或者你可以在辅助函数中使用额外的参数(因为额外的参数会改变函数的类型)来存储你提取的单词。这样做的结果是你最后反复使用了这个词,并且当你进行了递归时必须将其反转。

fun isLegal c = ord c >= 97 andalso ord c <= 122  (* Only lowercase ASCII letters *)
(* But why not use one of the following:
   fun isLegal c = Char.isAlpha c
   fun isLegal c = not (Char.isSpace c)  *)

fun next input =
    let fun extract (c::cs) word =
              if isLegal c
              then extract cs (c::word)
              else (rev word, c::cs)
          | extract [] word = (rev word, [])
    in extract input [] end

val next_test_1 =
    let val (w, r) = next (explode "hello world")
    in (implode w, implode r) = ("hello", " world")
    end

val next_test_2 = next [] = ([], [])