2015-10-25 66 views
0

我有一個字符列表[#"h", #"i", #" ", #"h", #"i"],我想從中獲取第一個字(每個空格之前的第一個字符序列)。試圖從字符列表中獲取第一個字

我寫了一個函數,它給了我這樣的警告:

標準輸入: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

這個功能已經在標準庫中存在:

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

但是如果你無論如何要建立這樣一個功能,看來你有時會返回([], [])並在其他時間一個列表。通常在遞歸函數中,您可以通過執行c :: recursive_f cs,但這是假設你的函數返回一個列表。相反,如果它返回一個元組,你就必須用這個元組來打開這個元組。模式在let表達式匹配:

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 [] = ([], []) 
+0

目標是不使用常見的ML函數,我們必須遞歸地完成整個事情。 但是你的建議真的很好!謝謝 – madcrazydrumma

相關問題