2016-11-08 95 views
0

我有這種特殊的類型,採取。查看SML中的記錄類型?

type taken = {course:string, student:int, grade:real}; 

我想查看這種類型的列表,找到匹配的課程和學生。如果我找到一個,那麼我必須將等級更改爲預設變量G.下面是我現在所擁有的。

exception unTaken; 
fun updateGrade (T:taken, []:taken list) = raise unTaken 
    | updateGrade (T, {course = #course(T), student = #student(T), ...}::rest) = 
    {course = #course(T), student = #student(T), grade = G} 
    | updateGrade (T, TL) = updateGrade (T, (tl TL)); 

如果達到取列表的末尾,我拋出一個異常。 第二種選擇是,如果它與T中的課程和名稱相匹配,則它將它設置爲相同課程和學生,但將G更改爲預設變量。否則,請繼續閱讀清單。


的問題,我不斷收到錯誤類似於下面

stdIn:3.21-3.28 Error: syntax error: deleting HASH ID 
stdIn:3.43-3.52 Error: syntax error: deleting HASH ID LPAREN 
stdIn:3.53 Error: syntax error found at RPAREN 

任何想法的人是怎麼回事?我還可以問如何去調試這些錯誤?

回答

2

以下是出問題的幾件事情:

  • 根據約定,保持小寫的變量名和值構造大寫。
  • 不要在同一模式下兩次使用相同的變量(您在幾個地方使用T)。一些模式匹配語言(Erlang,Prolog)允許這意味着這些變量覆蓋的值應該是等價的,但是Standard ML不支持這一點。
  • 請勿在格式中使用記錄獲取者#course/#student。它們是像功能一樣的宏。您可以對記錄的部分模式進行匹配,但語法略有不同(請參見下面的第二個示例)。

這裏有一個固定的版本:

fun updateGrade (t1 : taken, []) = raise unTaken 
    | updateGrade (t1 : taken, t2::ts) = 
    if #course t1 = #course t2 andalso #student t1 = #student t2 
    then t1 :: ts 
    else t2 :: updateGrade (t1, ts) 

這裏是一個固定的版本執行圖案記錄匹配:

fun updateGrade (t1 : taken, []) = raise unTaken 
    | updateGrade (t1 as { course = course1, student = student1, ... }, 
       (t2 as { course = course2, student = student2, ... })::ts) = 
    if course1 = course2 andalso student1 = student2 
    then t1 :: ts 
    else t2 :: updateGrade (t1, ts) 

可我還問怎麼繞過去調試這些錯誤?

由於編譯器仍然在一般情況下,固有無益時發生語法錯誤,我不知道還有更好的解決方案,而不是顯示代碼給別人,或者比較它針對你所知道的最類似的經典範例。標準ML沒有示例代碼,記錄語法比大多數其他語言更加繁瑣。

+0

我認爲你已經正確地確定了問題和解決方案,但我不確定,因爲你的術語對我來說似乎很陌生。是否「將#T統一爲'{course = #student(T),...}'」意味着「有一個子模式」{course = #student(T),...}「,變量'T'「? – ruakh

+0

@ruakh:我懷疑安德魯的意圖是兩次使用同一模式變量和有圖案只許成功,如果他們匹配相同的子結構。我要改寫我的回答讓更少的假設爲安德魯的意圖。 –

+0

你對編譯器消息的無用性質是正確的。根據我的經驗,SML/NJ是最有幫助的編譯器之一。你知道嗎,例如Poly/ML更好嗎? –