2015-11-03 64 views
0

我寫了下面的代碼:從列表中刪除真實元素 - SML

fun remove_element(nil, elem) = raise Empty 
    | remove_element(hd::tl, elem) = if(hd=elem) then tl else hd::remove_element(tl, elem); 

但功能(從列表中移除的元素ELEM)適用於INT。我需要讓它適用於真實數字,但我無法做到。我已經嘗試了很多重寫函數的方法,並且還使用了:真實但是這些會給我帶來錯誤。

有什麼建議嗎?

謝謝

+1

你的功能(在INT的情況下)將只從列表中刪除'elem'第一次出現 - 是設計?另外 - 如果'elem'不在列表中,即使列表本身可能不是空的,你的函數也會拋出'Empty'。也許你應該提出一個自定義錯誤。最後 - 除非這是作業,否則使用庫函數'List.filter'更有意義。 –

+0

比較第一個元素,如果它與elem相同,則刪除列表的第一個元素。這就是爲什麼else子句是hd :: remove_element(tl,elem),所以列表的其他元素不會消失。 – zeeks

+0

我瞭解您定義的邏輯,但不確定是否僅刪除第一次出現的「elem」是一個功能或錯誤。對我來說,將'[2,1,3,4]'作爲從[2,3,1,3,4]中移除3的結果看起來很奇怪,但這就是remove_element([2, 3,1,3,4],3);'回報。 –

回答

2

接受的答案本應讓您完成作業,所以我會針對您的問題的變化顯示其他兩種方法,而不用擔心爲您做作業。正如凱文約翰遜所說,不可能直接比較兩個實數。如果且僅當a<=bb<=a,因爲a=b可以間接地這樣做。通常這是一個錯誤,特別是如果有問題的列表是由數值計算產生的數字。但是 - 在某些情況下,比較實際的平等是有意義的,所以只要你清楚這是你想要的,你當然可以這樣做。這將導致你的代碼的以下修改:

fun remove_real([],x:real) = [] 
| remove_real(y::ys,x) = 
     if (y <= x andalso y >= x) then 
      remove_real(ys,x) 
     else 
      y::remove_real(ys,x); 

的幾點:

1)我改變了它從列表中,而不是僅僅在第一次出現刪除元素的所有事件。這涉及到將基礎案例更改爲返回空列表,因爲[]y刪除僅僅是[]而不是錯誤情況。另外,如果找到元素,而不是簡單地返回尾部,我會返回應用於尾部的遞歸調用,以便稍後刪除任何其他事件。您可以輕鬆修改代碼以使其更接近您的原始代碼。

2)我需要將顯式類型註釋x:real,以便SML可以推斷列表類型爲real list而不是類型int list

3)我換成[]nil審美的原因

4)我由y::ys取代你的格局hd::tl。首先,hdtl是內置函數 - 我沒有理由將這些標識符綁定到其他任何地方,即使它只是局部於函數定義。另一方面,模式中視覺混亂程度越低越好。

5)我更多地使用了空白。部分是品味的問題,但我認爲相當複雜的子句(如第二行)應該分成多行。

如果你想走包括比較實數的容錯的路線,我認爲將容差作爲顯式參數是最有意義的。我發現|x-y| < e比兩個不平等更自然。不幸的是,內置的abs僅適用於整數。如果x - y是真實的,則表達式

if x - y < 0.0 then y - x else x - y 

返回x - y絕對值(它翻轉在於它是neagative的情況下的符號)。作爲額外的好處 - 與0.0而不是0比較是SML需要推斷的類型。這導致:

fun remove_elem([],x,tol) = [] 
| remove_elem(y::ys,x,tol) = 
     if (if x - y < 0.0 then y - x else x - y) < tol then 
      remove_elem(ys,x,tol) 
     else 
      y::remove_elem(ys,x,tol); 

典型輸出:

- remove_real([2.0, 3.1, 3.14, 3.145, 3.14], 3.14); 
val it = [2.0,3.1,3.145] : real list 

- remove_elem([2.0, 3.1, 3.14, 3.145, 3.14], 3.14,0.01); 
val it = [2.0,3.1] : real list 

- remove_elem([2.0, 3.1, 3.14, 3.145, 3.14], 3.14,0.001); 
val it = [2.0,3.1,3.145] : real list 
+0

非常感謝您的回答! – zeeks

2

問題就在這裏:hd=elem 在諸如ML和Javascript語言,你不能直接比較兩個實數的實數必然舍入誤差。 您必須使用lambda範圍並改爲定義間隔。 elem - lambda < hd andalso elem + lambda > hd