接受的答案本應讓您完成作業,所以我會針對您的問題的變化顯示其他兩種方法,而不用擔心爲您做作業。正如凱文約翰遜所說,不可能直接比較兩個實數。如果且僅當a<=b
和b<=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
。首先,hd
和tl
是內置函數 - 我沒有理由將這些標識符綁定到其他任何地方,即使它只是局部於函數定義。另一方面,模式中視覺混亂程度越低越好。
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
你的功能(在INT的情況下)將只從列表中刪除'elem'第一次出現 - 是設計?另外 - 如果'elem'不在列表中,即使列表本身可能不是空的,你的函數也會拋出'Empty'。也許你應該提出一個自定義錯誤。最後 - 除非這是作業,否則使用庫函數'List.filter'更有意義。 –
比較第一個元素,如果它與elem相同,則刪除列表的第一個元素。這就是爲什麼else子句是hd :: remove_element(tl,elem),所以列表的其他元素不會消失。 – zeeks
我瞭解您定義的邏輯,但不確定是否僅刪除第一次出現的「elem」是一個功能或錯誤。對我來說,將'[2,1,3,4]'作爲從[2,3,1,3,4]中移除3的結果看起來很奇怪,但這就是remove_element([2, 3,1,3,4],3);'回報。 –